diff --git a/src/dbg/commands/cmd-tracing.cpp b/src/dbg/commands/cmd-tracing.cpp index 56ecf3b6..eb7b2abc 100644 --- a/src/dbg/commands/cmd-tracing.cpp +++ b/src/dbg/commands/cmd-tracing.cpp @@ -9,7 +9,7 @@ extern std::vector> RunToUserCodeBreakpoints; -static bool cbDebugConditionalTrace(void* callBack, bool stepOver, int argc, char* argv[]) +static bool cbDebugConditionalTrace(void(*callback)(), bool stepOver, int argc, char* argv[]) { if(IsArgumentsLessThan(argc, 2)) return false; @@ -29,21 +29,22 @@ static bool cbDebugConditionalTrace(void* callBack, bool stepOver, int argc, cha return false; } HistoryClear(); + if(stepOver) - StepOver(callBack); + StepOver((void*)callback); else - StepIntoWow64(callBack); + StepIntoWow64((void*)callback); return cbDebugRunInternal(argc, argv); } bool cbDebugTraceIntoConditional(int argc, char* argv[]) { - return cbDebugConditionalTrace((void*)cbTraceIntoConditionalStep, false, argc, argv); + return cbDebugConditionalTrace(cbTraceIntoConditionalStep, false, argc, argv); } bool cbDebugTraceOverConditional(int argc, char* argv[]) { - return cbDebugConditionalTrace((void*)cbTraceOverConditionalStep, true, argc, argv); + return cbDebugConditionalTrace(cbTraceOverConditionalStep, true, argc, argv); } bool cbDebugTraceIntoBeyondTraceRecord(int argc, char* argv[]) @@ -51,10 +52,10 @@ bool cbDebugTraceIntoBeyondTraceRecord(int argc, char* argv[]) if(argc == 1) { char* new_argv[] = { "tibt", "0" }; - return cbDebugConditionalTrace((void*)cbTraceIntoBeyondTraceRecordStep, false, 2, new_argv); + return cbDebugConditionalTrace(cbTraceIntoBeyondTraceRecordStep, false, 2, new_argv); } else - return cbDebugConditionalTrace((void*)cbTraceIntoBeyondTraceRecordStep, false, argc, argv); + return cbDebugConditionalTrace(cbTraceIntoBeyondTraceRecordStep, false, argc, argv); } bool cbDebugTraceOverBeyondTraceRecord(int argc, char* argv[]) @@ -62,10 +63,10 @@ bool cbDebugTraceOverBeyondTraceRecord(int argc, char* argv[]) if(argc == 1) { char* new_argv[] = { "tobt", "0" }; - return cbDebugConditionalTrace((void*)cbTraceOverBeyondTraceRecordStep, true, 2, new_argv); + return cbDebugConditionalTrace(cbTraceOverBeyondTraceRecordStep, true, 2, new_argv); } else - return cbDebugConditionalTrace((void*)cbTraceOverBeyondTraceRecordStep, true, argc, argv); + return cbDebugConditionalTrace(cbTraceOverBeyondTraceRecordStep, true, argc, argv); } bool cbDebugTraceIntoIntoTraceRecord(int argc, char* argv[]) @@ -73,10 +74,10 @@ bool cbDebugTraceIntoIntoTraceRecord(int argc, char* argv[]) if(argc == 1) { char* new_argv[] = { "tiit", "0" }; - return cbDebugConditionalTrace((void*)cbTraceIntoIntoTraceRecordStep, false, 2, new_argv); + return cbDebugConditionalTrace(cbTraceIntoIntoTraceRecordStep, false, 2, new_argv); } else - return cbDebugConditionalTrace((void*)cbTraceIntoIntoTraceRecordStep, false, argc, argv); + return cbDebugConditionalTrace(cbTraceIntoIntoTraceRecordStep, false, argc, argv); } bool cbDebugTraceOverIntoTraceRecord(int argc, char* argv[]) @@ -84,10 +85,10 @@ bool cbDebugTraceOverIntoTraceRecord(int argc, char* argv[]) if(argc == 1) { char* new_argv[] = { "toit", "0" }; - return cbDebugConditionalTrace((void*)cbTraceOverIntoTraceRecordStep, true, 2, new_argv); + return cbDebugConditionalTrace(cbTraceOverIntoTraceRecordStep, true, 2, new_argv); } else - return cbDebugConditionalTrace((void*)cbTraceOverIntoTraceRecordStep, true, argc, argv); + return cbDebugConditionalTrace(cbTraceOverIntoTraceRecordStep, true, argc, argv); } bool cbDebugRunToParty(int argc, char* argv[]) @@ -149,3 +150,15 @@ bool cbDebugTraceSetCommand(int argc, char* argv[]) } return true; } + +bool cbDebugTraceSetSwitchCondition(int argc, char* argv[]) +{ + auto condition = argc > 1 ? argv[1] : ""; + dputs(condition); + if(!dbgsettraceswitchcondition(condition)) + { + dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid expression \"%s\"\n"), condition); + return false; + } + return true; +} diff --git a/src/dbg/commands/cmd-tracing.h b/src/dbg/commands/cmd-tracing.h index e7a0c545..aa71473c 100644 --- a/src/dbg/commands/cmd-tracing.h +++ b/src/dbg/commands/cmd-tracing.h @@ -11,4 +11,5 @@ bool cbDebugTraceOverIntoTraceRecord(int argc, char* argv[]); bool cbDebugRunToParty(int argc, char* argv[]); bool cbDebugRunToUserCode(int argc, char* argv[]); bool cbDebugTraceSetLog(int argc, char* argv[]); -bool cbDebugTraceSetCommand(int argc, char* argv[]); \ No newline at end of file +bool cbDebugTraceSetCommand(int argc, char* argv[]); +bool cbDebugTraceSetSwitchCondition(int argc, char* argv[]); \ No newline at end of file diff --git a/src/dbg/debugger.cpp b/src/dbg/debugger.cpp index 1713a451..933c51cd 100644 --- a/src/dbg/debugger.cpp +++ b/src/dbg/debugger.cpp @@ -135,6 +135,21 @@ struct TraceState return cmdCondition ? cmdCondition->text : emptyString; } + bool InitSwitchCondition(const String & expression) + { + delete switchCondition; + switchCondition = nullptr; + if(expression.empty()) + return true; + switchCondition = new TextCondition(expression, ""); + return switchCondition->condition.IsValidExpression(); + } + + bool EvaluateSwitch(bool defaultValue) const + { + return switchCondition && switchCondition->Evaluate(defaultValue); + } + void Clear() { delete traceCondition; @@ -143,12 +158,15 @@ struct TraceState logCondition = nullptr; delete cmdCondition; cmdCondition = nullptr; + delete switchCondition; + switchCondition = nullptr; } private: TraceCondition* traceCondition = nullptr; TextCondition* logCondition = nullptr; TextCondition* cmdCondition = nullptr; + TextCondition* switchCondition = nullptr; String emptyString; }; @@ -244,6 +262,13 @@ bool dbgsettracecmd(const String & expression, const String & text) return traceState.InitCmdCondition(expression, text); } +bool dbgsettraceswitchcondition(const String & expression) +{ + if(dbgtraceactive()) + return false; + return traceState.InitSwitchCondition(expression); +} + bool dbgtraceactive() { return traceState.IsActive(); @@ -900,7 +925,7 @@ static void cbGenericBreakpoint(BP_TYPE bptype, void* ExceptionAddress = nullptr //TODO: commands like run/step etc will fuck up your shit varset("$breakpointcondition", breakCondition ? 1 : 0, false); varset("$breakpointlogcondition", logCondition ? 1 : 0, true); - _dbg_dbgcmddirectexec(bp.commandText); + cmddirectexec(bp.commandText); duint script_breakcondition; if(varget("$breakpointcondition", &script_breakcondition, nullptr, nullptr)) { @@ -1221,6 +1246,7 @@ static void cbTraceUniversalConditionalStep(duint cip, bool bStepInto, void(*cal breakCondition = info.stop; auto logCondition = traceState.EvaluateLog(true); auto cmdCondition = traceState.EvaluateCmd(breakCondition); + auto switchCondition = traceState.EvaluateSwitch(false); if(logCondition) //log { dprintf_untranslated("%s\n", stringformatinline(traceState.LogText()).c_str()); @@ -1230,10 +1256,13 @@ static void cbTraceUniversalConditionalStep(duint cip, bool bStepInto, void(*cal //TODO: commands like run/step etc will fuck up your shit varset("$tracecondition", breakCondition ? 1 : 0, false); varset("$tracelogcondition", logCondition ? 1 : 0, true); - _dbg_dbgcmddirectexec(traceState.CmdText().c_str()); + varset("$traceswitchcondition", switchCondition ? 1 : 0, false); + cmddirectexec(traceState.CmdText().c_str()); duint script_breakcondition; if(varget("$tracecondition", &script_breakcondition, nullptr, nullptr)) breakCondition = script_breakcondition != 0; + if(varget("$traceswitchcondition", &script_breakcondition, nullptr, nullptr)) + switchCondition = script_breakcondition != 0; } if(breakCondition) //break the debugger { @@ -1250,6 +1279,8 @@ static void cbTraceUniversalConditionalStep(duint cip, bool bStepInto, void(*cal { if(bTraceRecordEnabledDuringTrace) _dbg_dbgtraceexecute(cip); + if(switchCondition) //switch (invert) the step type once + bStepInto = !bStepInto; (bStepInto ? StepIntoWow64 : StepOver)(callback); } } diff --git a/src/dbg/debugger.h b/src/dbg/debugger.h index 862ce4f7..b069617f 100644 --- a/src/dbg/debugger.h +++ b/src/dbg/debugger.h @@ -107,6 +107,7 @@ duint dbggetdbgevents(); bool dbgsettracecondition(const String & expression, duint maxCount); bool dbgsettracelog(const String & expression, const String & text); bool dbgsettracecmd(const String & expression, const String & text); +bool dbgsettraceswitchcondition(const String & expression); bool dbgtraceactive(); void dbgsetdebuggeeinitscript(const char* fileName); const char* dbggetdebuggeeinitscript(); diff --git a/src/dbg/disasm_helper.cpp b/src/dbg/disasm_helper.cpp index cbf62e04..d7305a33 100644 --- a/src/dbg/disasm_helper.cpp +++ b/src/dbg/disasm_helper.cpp @@ -14,7 +14,6 @@ #include #include "datainst_helper.h" - duint disasmback(unsigned char* data, duint base, duint size, duint ip, int n) { int i; diff --git a/src/dbg/variable.cpp b/src/dbg/variable.cpp index a1863ca0..f01bd7f2 100644 --- a/src/dbg/variable.cpp +++ b/src/dbg/variable.cpp @@ -84,6 +84,7 @@ void varinit() varnew("$tracecounter", 0, VAR_READONLY); varnew("$tracecondition", 0, VAR_SYSTEM); varnew("$tracelogcondition", 0, VAR_READONLY); + varnew("$traceswitchcondition", 0, VAR_SYSTEM); // Read-only variables varnew("$lastalloc", 0, VAR_READONLY); // Last memory allocation diff --git a/src/dbg/x64dbg.cpp b/src/dbg/x64dbg.cpp index f8660996..c20fc1b4 100644 --- a/src/dbg/x64dbg.cpp +++ b/src/dbg/x64dbg.cpp @@ -219,6 +219,7 @@ static void registercommands() dbgcmdnew("RunToUserCode\1rtu", cbDebugRunToUserCode, true); //Run to user code dbgcmdnew("TraceSetLog\1SetTraceLog", cbDebugTraceSetLog, true); //Set trace log text + condition dbgcmdnew("TraceSetCommand\1SetTraceCommand", cbDebugTraceSetCommand, true); //Set trace command text + condition + dbgcmdnew("TraceSetSwitchCondition\1SetTraceSwitchCondition", cbDebugTraceSetSwitchCondition, true); //Set trace switch condition //thread control dbgcmdnew("createthread\1threadcreate\1newthread\1threadnew", cbDebugCreatethread, true); //create thread @@ -769,9 +770,7 @@ extern "C" DLL_EXPORT void _dbg_dbgexitsignal() extern "C" DLL_EXPORT bool _dbg_dbgcmddirectexec(const char* cmd) { - if(cmddirectexec(cmd) == false) - return false; - return true; + return cmddirectexec(cmd); } bool dbgisstopped() diff --git a/src/gui/Src/Gui/SimpleTraceDialog.cpp b/src/gui/Src/Gui/SimpleTraceDialog.cpp index 419b993c..99df2632 100644 --- a/src/gui/Src/Gui/SimpleTraceDialog.cpp +++ b/src/gui/Src/Gui/SimpleTraceDialog.cpp @@ -18,6 +18,7 @@ SimpleTraceDialog::SimpleTraceDialog(QWidget* parent) : ui->editLogCondition->setPlaceholderText(tr("Example: eax == 0 && ebx == 0")); ui->editCommandText->setPlaceholderText(tr("Example: eax=4;StepOut")); ui->editCommandCondition->setPlaceholderText(tr("Example: eax == 0 && ebx == 0")); + ui->editSwitchCondition->setPlaceholderText(tr("Example: eax == 0 && ebx == 0")); } SimpleTraceDialog::~SimpleTraceDialog() @@ -53,6 +54,12 @@ void SimpleTraceDialog::on_btnOk_clicked() QMessageBox::warning(this, tr("Error"), tr("Failed to set command text/condition!")); return; } + auto switchCondition = ui->editSwitchCondition->addHistoryClear(); + if(!DbgCmdExecDirect(QString("TraceSetSwitchCondition \"%1\"").arg(escapeText(switchCondition)).toUtf8().constData())) + { + QMessageBox::warning(this, tr("Error"), tr("Failed to set switch condition!")); + return; + } auto breakCondition = ui->editBreakCondition->addHistoryClear(); auto maxTraceCount = ui->spinMaxTraceCount->value(); if(!DbgCmdExecDirect(QString("%1 \"%2\", .%3").arg(mTraceCommand, escapeText(breakCondition)).arg(maxTraceCount).toUtf8().constData())) diff --git a/src/gui/Src/Gui/SimpleTraceDialog.ui b/src/gui/Src/Gui/SimpleTraceDialog.ui index 26fd10b5..4fd311e9 100644 --- a/src/gui/Src/Gui/SimpleTraceDialog.ui +++ b/src/gui/Src/Gui/SimpleTraceDialog.ui @@ -7,78 +7,33 @@ 0 0 502 - 218 + 244 - - + + - &Break Condition: + Hint: History is available in every text field with the Up/Down arrows! - - editBreakCondition + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - &Log Text: + + + + 1 - - editLogText + + 2147483647 - - - - - - - Lo&g Condition: - - - editLogCondition - - - - - - - - - - &Command Text: - - - editCommandText - - - - - - - - - - C&ommand Condition: - - - editCommandCondition - - - - - - @@ -95,17 +50,7 @@ - - - - 1 - - - 2147483647 - - - - + @@ -151,13 +96,78 @@ - - + + + + + - Hint: History is available in every text field with the Up/Down arrows! + &Break Condition: - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + editBreakCondition + + + + + + + + + + + + + Lo&g Condition: + + + editLogCondition + + + + + + + &Log Text: + + + editLogText + + + + + + + &Command Text: + + + editCommandText + + + + + + + C&ommand Condition: + + + editCommandCondition + + + + + + + + + + + + + + + + Switch Condition: @@ -189,11 +199,11 @@ reject() - 497 - 154 + 491 + 214 - 524 + 501 153