1
0
Fork 0

DBG+GUI: implemented trace switch condition

This commit is contained in:
mrexodia 2017-01-10 12:14:01 +01:00
parent 6f92218437
commit 9f7f649f7e
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
9 changed files with 158 additions and 96 deletions

View File

@ -9,7 +9,7 @@
extern std::vector<std::pair<duint, duint>> 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;
}

View File

@ -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[]);
bool cbDebugTraceSetCommand(int argc, char* argv[]);
bool cbDebugTraceSetSwitchCondition(int argc, char* argv[]);

View File

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

View File

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

View File

@ -14,7 +14,6 @@
#include <capstone_wrapper.h>
#include "datainst_helper.h"
duint disasmback(unsigned char* data, duint base, duint size, duint ip, int n)
{
int i;

View File

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

View File

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

View File

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

View File

@ -7,78 +7,33 @@
<x>0</x>
<y>0</y>
<width>502</width>
<height>218</height>
<height>244</height>
</rect>
</property>
<property name="windowTitle">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="lblBreakCondition">
<item row="8" column="0" colspan="2">
<widget class="QLabel" name="lblHint">
<property name="text">
<string>&amp;Break Condition:</string>
<string>Hint: History is available in every text field with the Up/Down arrows!</string>
</property>
<property name="buddy">
<cstring>editBreakCondition</cstring>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="HistoryLineEdit" name="editBreakCondition"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblLogText">
<property name="text">
<string>&amp;Log Text:</string>
<item row="5" column="1">
<widget class="QSpinBox" name="spinMaxTraceCount">
<property name="minimum">
<number>1</number>
</property>
<property name="buddy">
<cstring>editLogText</cstring>
<property name="maximum">
<number>2147483647</number>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="HistoryLineEdit" name="editLogText"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lblLogCondition">
<property name="text">
<string>Lo&amp;g Condition:</string>
</property>
<property name="buddy">
<cstring>editLogCondition</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="HistoryLineEdit" name="editLogCondition"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lblCommandText">
<property name="text">
<string>&amp;Command Text:</string>
</property>
<property name="buddy">
<cstring>editCommandText</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="HistoryLineEdit" name="editCommandText"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lblCommandCondition">
<property name="text">
<string>C&amp;ommand Condition:</string>
</property>
<property name="buddy">
<cstring>editCommandCondition</cstring>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="HistoryLineEdit" name="editCommandCondition"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="lblMaxTraceCount">
<property name="sizePolicy">
@ -95,17 +50,7 @@
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="spinMaxTraceCount">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>2147483647</number>
</property>
</widget>
</item>
<item row="6" column="1">
<item row="7" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
@ -151,13 +96,78 @@
</item>
</layout>
</item>
<item row="7" column="0" colspan="2">
<widget class="QLabel" name="lblHint">
<item row="0" column="1">
<widget class="HistoryLineEdit" name="editBreakCondition"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lblBreakCondition">
<property name="text">
<string>Hint: History is available in every text field with the Up/Down arrows!</string>
<string>&amp;Break Condition:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
<property name="buddy">
<cstring>editBreakCondition</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="HistoryLineEdit" name="editLogCondition"/>
</item>
<item row="1" column="1">
<widget class="HistoryLineEdit" name="editLogText"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lblLogCondition">
<property name="text">
<string>Lo&amp;g Condition:</string>
</property>
<property name="buddy">
<cstring>editLogCondition</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblLogText">
<property name="text">
<string>&amp;Log Text:</string>
</property>
<property name="buddy">
<cstring>editLogText</cstring>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lblCommandText">
<property name="text">
<string>&amp;Command Text:</string>
</property>
<property name="buddy">
<cstring>editCommandText</cstring>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lblCommandCondition">
<property name="text">
<string>C&amp;ommand Condition:</string>
</property>
<property name="buddy">
<cstring>editCommandCondition</cstring>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="HistoryLineEdit" name="editCommandCondition"/>
</item>
<item row="3" column="1">
<widget class="HistoryLineEdit" name="editCommandText"/>
</item>
<item row="6" column="1">
<widget class="HistoryLineEdit" name="editSwitchCondition"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="lblSwitchCondition">
<property name="text">
<string>Switch Condition:</string>
</property>
</widget>
</item>
@ -189,11 +199,11 @@
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>497</x>
<y>154</y>
<x>491</x>
<y>214</y>
</hint>
<hint type="destinationlabel">
<x>524</x>
<x>501</x>
<y>153</y>
</hint>
</hints>