1
0
Fork 0

Animate into (#1020)

* Translate some strings and export memiscodepage.

* fixed memory leaks in watch view

* warn the user if the breakpoint is not executable

* use dbgfunctions

* remove unused exports

* fix

* fix

* guard translate function with critical section

* DeleteCriticalSection

* Animate Into

* Animate Into

* Animate Into
This commit is contained in:
Torusrxxx 2016-08-30 10:59:40 +00:00 committed by Duncan Ogilvie
parent 9ecd535f51
commit 2938fa54c0
16 changed files with 169 additions and 25 deletions

View File

@ -25,6 +25,7 @@
#include "../bridge/bridgelist.h"
#include "tcpconnections.h"
#include "watch.h"
#include "animate.h"
static DBGFUNCTIONS _dbgfunctions;
@ -341,4 +342,5 @@ void dbgfunctionsinit()
_dbgfunctions.EnumTcpConnections = _enumtcpconnections;
_dbgfunctions.GetDbgEvents = dbggetdbgevents;
_dbgfunctions.MemIsCodePage = MemIsCodePage;
_dbgfunctions.AnimateCommand = _dbg_animatecommand;
}

View File

@ -146,6 +146,7 @@ typedef int (*MODGETPARTY)(duint base);
typedef void (*MODSETPARTY)(duint base, int party);
typedef bool(*WATCHISWATCHDOGTRIGGERED)(unsigned int id);
typedef bool(*MEMISCODEPAGE)(duint addr, bool refresh);
typedef bool(*ANIMATECOMMAND)(const char* command);
typedef struct DBGFUNCTIONS_
{
@ -201,6 +202,7 @@ typedef struct DBGFUNCTIONS_
MODSETPARTY ModSetParty;
WATCHISWATCHDOGTRIGGERED WatchIsWatchdogTriggered;
MEMISCODEPAGE MemIsCodePage;
ANIMATECOMMAND AnimateCommand;
} DBGFUNCTIONS;
#ifdef BUILD_DBG

View File

@ -33,6 +33,7 @@
#include "encodemap.h"
#include "argument.h"
#include "watch.h"
#include "animate.h"
static bool bOnlyCipAutoComments = false;
@ -883,6 +884,12 @@ extern "C" DLL_EXPORT duint _dbg_sendmessage(DBGMSG type, void* param1, void* pa
// Trim the buffer to fit inside MAX_PATH
strncpy_s(szSymbolCachePath, cachePath, _TRUNCATE);
}
duint animateInterval;
if(BridgeSettingGetUint("Engine", "AnimateInterval", &animateInterval))
_dbg_setanimateinterval(animateInterval);
else
_dbg_setanimateinterval(50); // 20 commands per second
}
break;

57
src/dbg/animate.cpp Normal file
View File

@ -0,0 +1,57 @@
#include "animate.h"
#include "x64_dbg.h"
static char animate_command[deflen];
static unsigned int animate_interval = 50;
HANDLE hAnimateThread = nullptr;
static DWORD WINAPI animateThread(void* arg1)
{
while(animate_command[0] != 0)
{
auto beforeTime = GetTickCount();
if(_dbg_dbgcmdexec(animate_command) != true)
// An error occurs
break;
auto currentTime = GetTickCount();
if(currentTime < (beforeTime + animate_interval))
{
Sleep(beforeTime + animate_interval - currentTime);
}
}
// Close the handle itself
HANDLE hAnimateThread2 = hAnimateThread;
hAnimateThread = nullptr;
CloseHandle(hAnimateThread2);
return 0;
}
bool _dbg_animatecommand(const char* command)
{
if(command) // Animate command
{
strcpy_s(animate_command, command);
if(hAnimateThread == nullptr)
{
hAnimateThread = CreateThread(NULL, 0, animateThread, nullptr, 0, nullptr);
}
}
else // command = null : stop animating
{
animate_command[0] = 0;
}
return true;
}
void _dbg_setanimateinterval(unsigned int milliseconds)
{
if(milliseconds <= 20)
animate_interval = 20;
else
animate_interval = milliseconds;
}
bool _dbg_isanimating()
{
return hAnimateThread != nullptr;
}

11
src/dbg/animate.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef ANIMATE_H
#define ANIMATE_H
bool _dbg_animatecommand(const char* command);
void _dbg_setanimateinterval(unsigned int milliseconds);
bool _dbg_isanimating();
inline void _dbg_animatestop()
{
_dbg_animatecommand(nullptr);
}
#endif //ANIMATE_H

View File

@ -121,7 +121,7 @@ void DbSave(DbLoadSaveType saveType)
else //remove database when nothing is in there
DeleteFileW(wdbpath.c_str());
dprintf("%ums\n", GetTickCount() - ticks);
dprintf(QT_TRANSLATE_NOOP("DBG", "%ums\n"), GetTickCount() - ticks);
json_decref(root); //free root
}
@ -230,7 +230,7 @@ void DbLoad(DbLoadSaveType loadType)
json_decref(root);
if(loadType != DbLoadSaveType::CommandLine)
dprintf("%ums\n", GetTickCount() - ticks);
dprintf(QT_TRANSLATE_NOOP("DBG", "%ums\n"), GetTickCount() - ticks);
}
void DbClose()

View File

@ -27,6 +27,7 @@
#include "TraceRecord.h"
#include "historycontext.h"
#include "taskthread.h"
#include "animate.h"
struct TraceCondition
{
@ -587,6 +588,7 @@ void cbPauseBreakpoint()
auto CIP = GetContextDataEx(hActiveThread, UE_CIP);
DeleteBPX(CIP);
DebugUpdateGuiSetStateAsync(CIP, true);
_dbg_animatestop(); // Stop animating when paused
// Trace record
_dbg_dbgtraceexecute(CIP);
//lock
@ -625,6 +627,7 @@ static void handleBreakCondition(const BREAKPOINT & bp, const void* ExceptionAdd
// Plugin callback
PLUG_CB_PAUSEDEBUG pauseInfo = { nullptr };
plugincbcall(CB_PAUSEDEBUG, &pauseInfo);
_dbg_animatestop(); // Stop animating when a breakpoint is hit
}
}
@ -710,7 +713,7 @@ static void cbGenericBreakpoint(BP_TYPE bptype, void* ExceptionAddress = nullptr
if(*bp.logText && logCondition) //log
{
dprintf("%s\n", stringformatinline(bp.logText).c_str());
dprintf_untranslated("%s\n", stringformatinline(bp.logText).c_str());
}
if(*bp.commandText && commandCondition) //command
{
@ -1228,6 +1231,7 @@ static void cbExitProcess(EXIT_PROCESS_DEBUG_INFO* ExitProcess)
PLUG_CB_EXITPROCESS callbackInfo;
callbackInfo.ExitProcess = ExitProcess;
plugincbcall(CB_EXITPROCESS, &callbackInfo);
_dbg_animatestop(); // Stop animating
//unload main module
SafeSymUnloadModule64(fdProcessInfo->hProcess, pCreateProcessBase);
//history
@ -1576,12 +1580,14 @@ static void cbException(EXCEPTION_DEBUG_INFO* ExceptionData)
else
dputs(QT_TRANSLATE_NOOP("DBG", "Detached!"));
isDetachedByUser = false;
_dbg_animatestop(); // Stop animating
return;
}
else if(isPausedByUser)
{
dputs(QT_TRANSLATE_NOOP("DBG", "paused!"));
SetNextDbgContinueStatus(DBG_CONTINUE);
_dbg_animatestop(); // Stop animating
//update memory map
MemUpdateMap();
DebugUpdateGuiSetStateAsync(GetContextDataEx(hActiveThread, UE_CIP), true);
@ -1810,9 +1816,9 @@ bool cbBreakpointList(const BREAKPOINT* bp)
type = "GP";
bool enabled = bp->enabled;
if(*bp->name)
dprintf("%d:%s:%p:\"%s\"\n", enabled, type, bp->addr, bp->name);
dprintf_untranslated("%d:%s:%p:\"%s\"\n", enabled, type, bp->addr, bp->name);
else
dprintf("%d:%s:%p\n", enabled, type, bp->addr);
dprintf_untranslated("%d:%s:%p\n", enabled, type, bp->addr);
return true;
}

View File

@ -25,6 +25,7 @@
#include "function.h"
#include "historycontext.h"
#include "taskthread.h"
#include "animate.h"
static bool bScyllaLoaded = false;
duint LoadLibThreadID;
@ -1616,8 +1617,16 @@ CMDRESULT cbDebugPause(int argc, char* argv[])
{
if(!dbgisrunning())
{
dputs(QT_TRANSLATE_NOOP("DBG", "Program is not running"));
return STATUS_ERROR;
if(_dbg_isanimating())
{
_dbg_animatestop(); // pause when animating
return STATUS_CONTINUE;
}
else
{
dputs(QT_TRANSLATE_NOOP("DBG", "Program is not running"));
return STATUS_ERROR;
}
}
if(SuspendThread(hActiveThread) == -1)
{

View File

@ -74,13 +74,13 @@ void pluginload(const char* pluginDir)
pluginData.hPlugin = LoadLibraryW(StringUtils::Utf8ToUtf16(szPluginPath).c_str()); //load the plugin library
if(!pluginData.hPlugin)
{
dprintf("[PLUGIN] Failed to load plugin: %s\n", StringUtils::Utf16ToUtf8(foundData.cFileName).c_str());
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] Failed to load plugin: %s\n"), StringUtils::Utf16ToUtf8(foundData.cFileName).c_str());
continue;
}
pluginData.pluginit = (PLUGINIT)GetProcAddress(pluginData.hPlugin, "pluginit");
if(!pluginData.pluginit)
{
dprintf("[PLUGIN] Export \"pluginit\" not found in plugin: %s\n", StringUtils::Utf16ToUtf8(foundData.cFileName).c_str());
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] Export \"pluginit\" not found in plugin: %s\n"), StringUtils::Utf16ToUtf8(foundData.cFileName).c_str());
FreeLibrary(pluginData.hPlugin);
continue;
}
@ -189,18 +189,18 @@ void pluginload(const char* pluginDir)
//init plugin
if(!pluginData.pluginit(&pluginData.initStruct))
{
dprintf("[PLUGIN] pluginit failed for plugin: %s\n", StringUtils::Utf16ToUtf8(foundData.cFileName).c_str());
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] pluginit failed for plugin: %s\n"), StringUtils::Utf16ToUtf8(foundData.cFileName).c_str());
FreeLibrary(pluginData.hPlugin);
continue;
}
else if(pluginData.initStruct.sdkVersion < PLUG_SDKVERSION) //the plugin SDK is not compatible
{
dprintf("[PLUGIN] %s is incompatible with this SDK version\n", pluginData.initStruct.pluginName);
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] %s is incompatible with this SDK version\n"), pluginData.initStruct.pluginName);
FreeLibrary(pluginData.hPlugin);
continue;
}
else
dprintf("[PLUGIN] %s v%d Loaded!\n", pluginData.initStruct.pluginName, pluginData.initStruct.pluginVersion);
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] %s v%d Loaded!\n"), pluginData.initStruct.pluginName, pluginData.initStruct.pluginVersion);
SectionLocker<LockPluginMenuList, false> menuLock; //exclusive lock
@ -208,7 +208,7 @@ void pluginload(const char* pluginDir)
int hNewMenu = GuiMenuAdd(GUI_PLUGIN_MENU, pluginData.initStruct.pluginName);
if(hNewMenu == -1)
{
dprintf("[PLUGIN] GuiMenuAdd(GUI_PLUGIN_MENU) failed for plugin: %s\n", pluginData.initStruct.pluginName);
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] GuiMenuAdd(GUI_PLUGIN_MENU) failed for plugin: %s\n"), pluginData.initStruct.pluginName);
pluginData.hMenu = -1;
}
else
@ -225,7 +225,7 @@ void pluginload(const char* pluginDir)
hNewMenu = GuiMenuAdd(GUI_DISASM_MENU, pluginData.initStruct.pluginName);
if(hNewMenu == -1)
{
dprintf("[PLUGIN] GuiMenuAdd(GUI_DISASM_MENU) failed for plugin: %s\n", pluginData.initStruct.pluginName);
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] GuiMenuAdd(GUI_DISASM_MENU) failed for plugin: %s\n"), pluginData.initStruct.pluginName);
pluginData.hMenu = -1;
}
else
@ -242,7 +242,7 @@ void pluginload(const char* pluginDir)
hNewMenu = GuiMenuAdd(GUI_DUMP_MENU, pluginData.initStruct.pluginName);
if(hNewMenu == -1)
{
dprintf("[PLUGIN] GuiMenuAdd(GUI_DUMP_MENU) failed for plugin: %s\n", pluginData.initStruct.pluginName);
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] GuiMenuAdd(GUI_DUMP_MENU) failed for plugin: %s\n"), pluginData.initStruct.pluginName);
pluginData.hMenu = -1;
}
else
@ -259,7 +259,7 @@ void pluginload(const char* pluginDir)
hNewMenu = GuiMenuAdd(GUI_STACK_MENU, pluginData.initStruct.pluginName);
if(hNewMenu == -1)
{
dprintf("[PLUGIN] GuiMenuAdd(GUI_STACK_MENU) failed for plugin: %s\n", pluginData.initStruct.pluginName);
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] GuiMenuAdd(GUI_STACK_MENU) failed for plugin: %s\n"), pluginData.initStruct.pluginName);
pluginData.hMenu = -1;
}
else
@ -451,7 +451,7 @@ bool plugincmdregister(int pluginHandle, const char* command, CBPLUGINCOMMAND cb
EXCLUSIVE_ACQUIRE(LockPluginCommandList);
pluginCommandList.push_back(plugCmd);
EXCLUSIVE_RELEASE();
dprintf("[PLUGIN] command \"%s\" registered!\n", command);
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] command \"%s\" registered!\n"), command);
return true;
}
@ -475,7 +475,7 @@ bool plugincmdunregister(int pluginHandle, const char* command)
EXCLUSIVE_RELEASE();
if(!dbgcmddel(command))
return false;
dprintf("[PLUGIN] command \"%s\" unregistered!\n", command);
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] command \"%s\" unregistered!\n"), command);
return true;
}
}
@ -711,7 +711,7 @@ bool pluginexprfuncregister(int pluginHandle, const char* name, int argc, CBPLUG
EXCLUSIVE_ACQUIRE(LockPluginExprfunctionList);
pluginExprfunctionList.push_back(plugExprfunction);
EXCLUSIVE_RELEASE();
dprintf("[PLUGIN] expression function \"%s\" registered!\n", name);
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] expression function \"%s\" registered!\n"), name);
return true;
}
@ -727,7 +727,7 @@ bool pluginexprfuncunregister(int pluginHandle, const char* name)
EXCLUSIVE_RELEASE();
if(!ExpressionFunctions::Unregister(name))
return false;
dprintf("[PLUGIN] expression function \"%s\" unregistered!\n", name);
dprintf(QT_TRANSLATE_NOOP("DBG", "[PLUGIN] expression function \"%s\" unregistered!\n"), name);
return true;
}
}

View File

@ -437,8 +437,7 @@ extern "C" DLL_EXPORT const char* _dbg_dbginit()
if(!EngineCheckStructAlignment(UE_STRUCT_TITAN_ENGINE_CONTEXT, sizeof(TITAN_ENGINE_CONTEXT_t)))
return "Invalid TITAN_ENGINE_CONTEXT_t alignment!";
if(sizeof(TITAN_ENGINE_CONTEXT_t) != sizeof(REGISTERCONTEXT))
return "Invalid REGISTERCONTEXT alignment!";
static_assert(sizeof(TITAN_ENGINE_CONTEXT_t) == sizeof(REGISTERCONTEXT), "Invalid REGISTERCONTEXT alignment!");
dputs(QT_TRANSLATE_NOOP("DBG", "Initializing wait objects..."));
waitinitialize();

View File

@ -32,6 +32,7 @@
<ClCompile Include="analysis\LinearPass.cpp" />
<ClCompile Include="analysis\recursiveanalysis.cpp" />
<ClCompile Include="analysis\xrefsanalysis.cpp" />
<ClCompile Include="animate.cpp" />
<ClCompile Include="argument.cpp" />
<ClCompile Include="assemble.cpp" />
<ClCompile Include="bookmark.cpp" />
@ -123,6 +124,7 @@
<ClInclude Include="analysis\LinearPass.h" />
<ClInclude Include="analysis\recursiveanalysis.h" />
<ClInclude Include="analysis\xrefsanalysis.h" />
<ClInclude Include="animate.h" />
<ClInclude Include="argument.h" />
<ClInclude Include="assemble.h" />
<ClInclude Include="bookmark.h" />

View File

@ -347,6 +347,9 @@
<ClCompile Include="exprfunc.cpp">
<Filter>Source Files\Debugger Core</Filter>
</ClCompile>
<ClCompile Include="animate.cpp">
<Filter>Source Files\Utilities</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="x64_dbg.h">
@ -790,5 +793,8 @@
<ClInclude Include="yara\yara\threading.h">
<Filter>Header Files\Third Party\yara\yara</Filter>
</ClInclude>
<ClInclude Include="animate.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -326,6 +326,9 @@ MainWindow::MainWindow(QWidget* parent)
makeCommandAction(ui->actionseStepInto, "seStepInto");
makeCommandAction(ui->actionseStepOver, "seStepOver");
makeCommandAction(ui->actionseRun, "seRun");
connect(ui->actionAnimateInto, SIGNAL(triggered()), this, SLOT(animateIntoSlot()));
connect(ui->actionAnimateOver, SIGNAL(triggered()), this, SLOT(animateOverSlot()));
connect(ui->actionAnimateCommand, SIGNAL(triggered()), this, SLOT(animateCommandSlot()));
connect(mCpuWidget->getDisasmWidget(), SIGNAL(updateWindowTitle(QString)), this, SLOT(updateWindowTitleSlot(QString)));
connect(mCpuWidget->getDisasmWidget(), SIGNAL(displayReferencesWidget()), this, SLOT(displayReferencesWidget()));
@ -1656,3 +1659,20 @@ void MainWindow::setFavouriteItemShortcut(int type, const QString & name, const
}
}
}
void MainWindow::animateIntoSlot()
{
DbgFunctions()->AnimateCommand("StepInto");
}
void MainWindow::animateOverSlot()
{
DbgFunctions()->AnimateCommand("StepOver");
}
void MainWindow::animateCommandSlot()
{
QString command;
if(SimpleInputBox(this, tr("Animate command"), "", command, tr("Example: StepInto")))
DbgFunctions()->AnimateCommand(command.toUtf8().constData());
}

View File

@ -63,6 +63,9 @@ public slots:
void displayAboutWidget();
void execTocnd();
void execTicnd();
void animateIntoSlot();
void animateOverSlot();
void animateCommandSlot();
void openFile();
void restartDebugging();
void displayBreakpointWidget();

View File

@ -109,16 +109,19 @@
<addaction name="actionseStepInto"/>
<addaction name="actionStepIntoSource"/>
<addaction name="actionTicnd"/>
<addaction name="actionAnimateInto"/>
<addaction name="actionStepOver"/>
<addaction name="actioneStepOver"/>
<addaction name="actionseStepOver"/>
<addaction name="actionStepOverSource"/>
<addaction name="actionRtu"/>
<addaction name="actionTocnd"/>
<addaction name="actionAnimateOver"/>
<addaction name="separator"/>
<addaction name="actionRtr"/>
<addaction name="actioneRtr"/>
<addaction name="actionSkipNextInstruction"/>
<addaction name="separator"/>
<addaction name="actionAnimateCommand"/>
<addaction name="menuTrace_record"/>
<addaction name="actionInstrUndo"/>
<addaction name="separator"/>
@ -1004,6 +1007,21 @@
<string>Blog</string>
</property>
</action>
<action name="actionAnimateInto">
<property name="text">
<string>Animate into</string>
</property>
</action>
<action name="actionAnimateOver">
<property name="text">
<string>Animate over</string>
</property>
</action>
<action name="actionAnimateCommand">
<property name="text">
<string>Animate command...</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>

View File

@ -188,7 +188,8 @@ SOURCES += \
dbg/analysis/linearanalysis.cpp \
dbg/analysis/LinearPass.cpp \
dbg/analysis/recursiveanalysis.cpp \
dbg/analysis/xrefsanalysis.cpp
dbg/analysis/xrefsanalysis.cpp \
dbg/animate.cpp
TRANSLATIONS = \
gui/Translations/x64dbg.ts
@ -393,7 +394,8 @@ HEADERS += \
dbg/analysis/linearanalysis.h \
dbg/analysis/LinearPass.h \
dbg/analysis/recursiveanalysis.h \
dbg/analysis/xrefsanalysis.h
dbg/analysis/xrefsanalysis.h \
dbg/animate.h
FORMS += \
gui/Src/Gui/AppearanceDialog.ui \