diff --git a/src/dbg/debugger.cpp b/src/dbg/debugger.cpp index 15a230a8..c2ecbe9b 100644 --- a/src/dbg/debugger.cpp +++ b/src/dbg/debugger.cpp @@ -27,6 +27,7 @@ static PROCESS_INFORMATION g_pi = {0, 0, 0, 0}; static char szBaseFileName[MAX_PATH] = ""; +ExpressionParser* RtcondCondition; static bool bFileIsDll = false; static duint pDebuggedBase = 0; static duint pCreateProcessBase = 0; @@ -774,6 +775,48 @@ void cbRtrStep() StepOver((void*)cbRtrStep); } +void cbTOCNDStep() +{ + duint value = 1; + if (!RtcondCondition || RtcondCondition->Calculate(value, valuesignedcalc()) == false) + { + delete RtcondCondition; + RtcondCondition = nullptr; + cbRtrFinalStep(); + } + else if (value != 0) + { + delete RtcondCondition; + RtcondCondition = nullptr; + cbRtrFinalStep(); + } + else + { + StepOver((void*)cbTOCNDStep); + } +} + +void cbTICNDStep() +{ + duint value = 1; + if (!RtcondCondition || RtcondCondition->Calculate(value, valuesignedcalc()) == false) + { + delete RtcondCondition; + RtcondCondition = nullptr; + cbRtrFinalStep(); + } + else if (value != 0) + { + delete RtcondCondition; + RtcondCondition = nullptr; + cbRtrFinalStep(); + } + else + { + StepInto((void*)cbTICNDStep); + } +} + static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo) { void* base = CreateProcessInfo->lpBaseOfImage; diff --git a/src/dbg/debugger.h b/src/dbg/debugger.h index 584d54f0..a4532c65 100644 --- a/src/dbg/debugger.h +++ b/src/dbg/debugger.h @@ -6,6 +6,7 @@ #include "command.h" #include "breakpoint.h" #include "undocumented.h" +#include "expressionparser.h" #include "value.h" #include "_plugins.h" @@ -104,6 +105,8 @@ bool cbDisableAllMemoryBreakpoints(const BREAKPOINT* bp); bool cbBreakpointList(const BREAKPOINT* bp); bool cbDeleteAllMemoryBreakpoints(const BREAKPOINT* bp); bool cbDeleteAllHardwareBreakpoints(const BREAKPOINT* bp); +void cbTOCNDStep(); +void cbTICNDStep(); DWORD WINAPI threadAttachLoop(void* lpParameter); void cbDetach(); bool cbSetModuleBreakpoints(const BREAKPOINT* bp); @@ -114,6 +117,7 @@ extern HANDLE hActiveThread; extern HANDLE hProcessToken; extern char szFileName[MAX_PATH]; extern char szSymbolCachePath[MAX_PATH]; +extern ExpressionParser* RtcondCondition; extern bool bUndecorateSymbolNames; extern bool bEnableSourceDebugging; diff --git a/src/dbg/debugger_commands.cpp b/src/dbg/debugger_commands.cpp index f897cb3c..d3a4ceee 100644 --- a/src/dbg/debugger_commands.cpp +++ b/src/dbg/debugger_commands.cpp @@ -1255,6 +1255,52 @@ CMDRESULT cbDebugeRtr(int argc, char* argv[]) return cbDebugRtr(argc, argv); } +CMDRESULT cbDebugTocnd(int argc, char* argv[]) +{ + if (argc > 2) + { + dputs("Too many arguments."); + return STATUS_ERROR; + } + else if (argc < 1) + { + dputs("Too few arguments."); + return STATUS_ERROR; + } + if (RtcondCondition != nullptr) + { + dputs("Tracing is busy now."); + return STATUS_ERROR; + } + RtcondCondition = new ExpressionParser(argv[1]); + StepOver((void*)cbTOCNDStep); + cbDebugRun(argc, argv); + return STATUS_CONTINUE; +} + +CMDRESULT cbDebugTicnd(int argc, char* argv[]) +{ + if (argc > 2) + { + dputs("Too many arguments."); + return STATUS_ERROR; + } + else if (argc < 1) + { + dputs("Too few arguments."); + return STATUS_ERROR; + } + if (RtcondCondition != nullptr) + { + dputs("Tracing is busy now."); + return STATUS_ERROR; + } + RtcondCondition = new ExpressionParser(argv[1]); + StepInto((void*)cbTICNDStep); + cbDebugRun(argc, argv); + return STATUS_CONTINUE; +} + CMDRESULT cbDebugAlloc(int argc, char* argv[]) { duint size = 0x1000; diff --git a/src/dbg/debugger_commands.h b/src/dbg/debugger_commands.h index 4c03baac..478d50ab 100644 --- a/src/dbg/debugger_commands.h +++ b/src/dbg/debugger_commands.h @@ -56,6 +56,8 @@ CMDRESULT cbDebugStepOver(int argc, char* argv[]); CMDRESULT cbDebugeStepOver(int argc, char* argv[]); CMDRESULT cbDebugSingleStep(int argc, char* argv[]); CMDRESULT cbDebugeSingleStep(int argc, char* argv[]); +CMDRESULT cbDebugTocnd(int argc, char* argv[]); +CMDRESULT cbDebugTicnd(int argc, char* argv[]); CMDRESULT cbDebugHide(int argc, char* argv[]); CMDRESULT cbDebugDisasm(int argc, char* argv[]); CMDRESULT cbDebugRtr(int argc, char* argv[]); diff --git a/src/dbg/x64_dbg.cpp b/src/dbg/x64_dbg.cpp index 6cc36f86..c853782e 100644 --- a/src/dbg/x64_dbg.cpp +++ b/src/dbg/x64_dbg.cpp @@ -89,6 +89,8 @@ static void registercommands() dbgcmdnew("eSingleStep\1esstep\1esst", cbDebugeSingleStep, true); //SingleStep arg1:count + skip first chance exceptions dbgcmdnew("StepOut\1rtr", cbDebugRtr, true); //rtr dbgcmdnew("eStepOut\1ertr", cbDebugeRtr, true); //rtr + skip first chance exceptions + dbgcmdnew("tocnd", cbDebugTocnd, true); //tocnd + dbgcmdnew("ticnd", cbDebugTicnd, true); //ticnd dbgcmdnew("DebugContinue\1con", cbDebugContinue, true); //set continue status @@ -134,8 +136,8 @@ static void registercommands() //breakpoints (conditional) dbgcmdnew("SetBreakpointName\1bpname", cbDebugSetBPXName, true); //set breakpoint name - dbgcmdnew("SetBreakpointCondition\1bpcond", cbDebugSetBPXCondition, true); //set breakpoint breakCondition - dbgcmdnew("SetBreakpointLog\1bplog", cbDebugSetBPXLog, true); //set breakpoint logText + dbgcmdnew("SetBreakpointCondition\1bpcond\1bpcnd", cbDebugSetBPXCondition, true); //set breakpoint breakCondition + dbgcmdnew("SetBreakpointLog\1bplog\1bpl", cbDebugSetBPXLog, true); //set breakpoint logText dbgcmdnew("SetBreakpointLogCondition\1bplogcondition", cbDebugSetBPXLogCondition, true); //set breakpoint logCondition dbgcmdnew("SetBreakpointCommand", cbDebugSetBPXCommand, true); //set breakpoint command on hit dbgcmdnew("SetBreakpointCommandCondition", cbDebugSetBPXCommandCondition, true); //set breakpoint commandCondition diff --git a/src/gui/Src/Gui/MainWindow.cpp b/src/gui/Src/Gui/MainWindow.cpp index b1b3f870..2c392af3 100644 --- a/src/gui/Src/Gui/MainWindow.cpp +++ b/src/gui/Src/Gui/MainWindow.cpp @@ -232,6 +232,8 @@ MainWindow::MainWindow(QWidget* parent) connect(ui->actioneStepInto, SIGNAL(triggered()), this, SLOT(execeStepInto())); connect(ui->actioneRun, SIGNAL(triggered()), this, SLOT(execeRun())); connect(ui->actioneRtr, SIGNAL(triggered()), this, SLOT(execeRtr())); + connect(ui->actionTicnd, SIGNAL(triggered()), this, SLOT(execTicnd())); + connect(ui->actionTocnd, SIGNAL(triggered()), this, SLOT(execTocnd())); connect(ui->actionSkipNextInstruction, SIGNAL(triggered()), this, SLOT(execSkip())); connect(ui->actionScript, SIGNAL(triggered()), this, SLOT(displayScriptWidget())); connect(ui->actionRunSelection, SIGNAL(triggered()), this, SLOT(runSelection())); @@ -591,6 +593,26 @@ void MainWindow::execRtr() DbgCmdExec("rtr"); } +void MainWindow::execTicnd() +{ + if(!DbgIsDebugging()) + return; + LineEditDialog mLineEdit(this); + mLineEdit.setWindowTitle(tr("Enter trace into finishing condition.")); + if(mLineEdit.exec() == QDialog::Accepted) + DbgCmdExec(QString("ticnd \"%1\"").arg(mLineEdit.editText).toUtf8().constData()); +} + +void MainWindow::execTocnd() +{ + if(!DbgIsDebugging()) + return; + LineEditDialog mLineEdit(this); + mLineEdit.setWindowTitle(tr("Enter trace over finishing condition.")); + if(mLineEdit.exec() == QDialog::Accepted) + DbgCmdExec(QString("tocnd \"%1\"").arg(mLineEdit.editText).toUtf8().constData()); +} + void MainWindow::displayMemMapWidget() { showQWidgetTab(mMemMapView); diff --git a/src/gui/Src/Gui/MainWindow.h b/src/gui/Src/Gui/MainWindow.h index c99a9773..9f362a84 100644 --- a/src/gui/Src/Gui/MainWindow.h +++ b/src/gui/Src/Gui/MainWindow.h @@ -62,6 +62,8 @@ public slots: void execClose(); void execRun(); void execRtr(); + void execTocnd(); + void execTicnd(); void openFile(); void execPause(); void startScylla(); diff --git a/src/gui/Src/Gui/MainWindow.ui b/src/gui/Src/Gui/MainWindow.ui index f247426d..8648b3b3 100644 --- a/src/gui/Src/Gui/MainWindow.ui +++ b/src/gui/Src/Gui/MainWindow.ui @@ -85,8 +85,10 @@ + + @@ -765,6 +767,16 @@ Handles + + + Trace over until condition + + + + + Trace into until condition + +