/
githubmirror
/
x64dbg
Обзор
Документация
Войти
/
githubmirror
/
x64dbg
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
development
src/dbg/watch.cpp
433 строки
14 KB
morsisko
DBG: Fixed issue mentioned in comment to #2310 - force value refresh after watch expression change
15 дек 2020, 19:39
15 дек 2020, 19:39
b8db2b2
Код
Авторство
О чём код?
#include "watch.h" #include "console.h" #include "threading.h" #include "debugger.h" #include "taskthread.h" #include <Windows.h> std::map<unsigned int, WatchExpr*> watchexpr; unsigned int idCounter = 1; WatchExpr::WatchExpr(const char* name, const char* expression, WATCHVARTYPE type) : expr(expression), haveCurrValue(false), varType(type), currValue(0), watchdogTriggered(false), watchWindow(0), watchdogMode(MODE_DISABLED) { if(!expr.IsValidExpression()) varType = WATCHVARTYPE::TYPE_INVALID; strcpy_s(this->WatchName, name); } duint WatchExpr::getIntValue() { duint origVal = currValue; if(varType == WATCHVARTYPE::TYPE_UINT || varType == WATCHVARTYPE::TYPE_INT || varType == WATCHVARTYPE::TYPE_FLOAT || varType == WATCHVARTYPE::TYPE_ASCII || varType == WATCHVARTYPE::TYPE_UNICODE) { duint val; bool ok = expr.Calculate(val, varType == WATCHVARTYPE::TYPE_INT, false); if(ok) { currValue = val; haveCurrValue = true; if(getType() != WATCHVARTYPE::TYPE_INVALID) { switch(getWatchdogMode()) { default: case WATCHDOGMODE::MODE_DISABLED: break; case WATCHDOGMODE::MODE_ISTRUE: if(currValue != 0) { duint cip = GetContextDataEx(hActiveThread, UE_CIP); dprintf(QT_TRANSLATE_NOOP("DBG", "Watchdog %s (expression \"%s\") is triggered at %p ! Original value: %p, New value: %p\n"), WatchName, getExpr().c_str(), cip, origVal, currValue); watchdogTriggered = 1; } break; case WATCHDOGMODE::MODE_ISFALSE: if(currValue == 0) { duint cip = GetContextDataEx(hActiveThread, UE_CIP); dprintf(QT_TRANSLATE_NOOP("DBG", "Watchdog %s (expression \"%s\") is triggered at %p ! Original value: %p, New value: %p\n"), WatchName, getExpr().c_str(), cip, origVal, currValue); watchdogTriggered = 1; } break; case WATCHDOGMODE::MODE_CHANGED: if(currValue != origVal || !haveCurrValue) { duint cip = GetContextDataEx(hActiveThread, UE_CIP); dprintf(QT_TRANSLATE_NOOP("DBG", "Watchdog %s (expression \"%s\") is triggered at %p ! Original value: %p, New value: %p\n"), WatchName, getExpr().c_str(), cip, origVal, currValue); watchdogTriggered = 1; } break; case WATCHDOGMODE::MODE_UNCHANGED: if(currValue == origVal || !haveCurrValue) { duint cip = GetContextDataEx(hActiveThread, UE_CIP); dprintf(QT_TRANSLATE_NOOP("DBG", "Watchdog %s (expression \"%s\") is triggered at %p ! Original value: %p, New value: %p\n"), WatchName, getExpr().c_str(), cip, origVal, currValue); watchdogTriggered = 1; } break; } } return val; } } currValue = 0; haveCurrValue = false; return 0; } bool WatchExpr::modifyExpr(const char* expression, WATCHVARTYPE type) { ExpressionParser b(expression); if(b.IsValidExpression()) { expr = b; varType = type; this->getIntValue(); haveCurrValue = false; return true; } else return false; } void WatchExpr::modifyName(const char* newName) { strcpy_s(WatchName, newName); } // Update GUI void GuiUpdateWatchViewAsync() { static TaskThread_<decltype(&GuiUpdateWatchView)> task(&GuiUpdateWatchView); task.WakeUp(); } // Global functions // Clear all watch void WatchClear() { if(!watchexpr.empty()) { for(auto i : watchexpr) delete i.second; watchexpr.clear(); } } unsigned int WatchAddExprUnlocked(const char* expr, WATCHVARTYPE type) { unsigned int newid = InterlockedExchangeAdd((volatile long*)&idCounter, 1); char DefaultName[MAX_WATCH_NAME_SIZE]; sprintf_s(DefaultName, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Watch %u")), newid); WatchExpr* newWatch = new WatchExpr(DefaultName, expr, type); auto temp = watchexpr.emplace(std::make_pair(newid, newWatch)); if(temp.second) { newWatch->getIntValue(); return newid; } else { delete newWatch; return 0; } } unsigned int WatchAddExpr(const char* expr, WATCHVARTYPE type) { EXCLUSIVE_ACQUIRE(LockWatch); unsigned int id = WatchAddExprUnlocked(expr, type); EXCLUSIVE_RELEASE(); GuiUpdateWatchView(); return id; } bool WatchModifyExpr(unsigned int id, const char* expr, WATCHVARTYPE type) { EXCLUSIVE_ACQUIRE(LockWatch); auto obj = watchexpr.find(id); if(obj != watchexpr.end()) { bool success = obj->second->modifyExpr(expr, type); EXCLUSIVE_RELEASE(); GuiUpdateWatchView(); return success; } else return false; } void WatchModifyNameUnlocked(unsigned int id, const char* newName) { auto obj = watchexpr.find(id); if(obj != watchexpr.end()) { obj->second->modifyName(newName); } } void WatchModifyName(unsigned int id, const char* newName) { EXCLUSIVE_ACQUIRE(LockWatch); WatchModifyNameUnlocked(id, newName); EXCLUSIVE_RELEASE(); GuiUpdateWatchViewAsync(); } void WatchDelete(unsigned int id) { EXCLUSIVE_ACQUIRE(LockWatch); auto x = watchexpr.find(id); if(x != watchexpr.end()) { delete x->second; watchexpr.erase(x); EXCLUSIVE_RELEASE(); GuiUpdateWatchViewAsync(); } } void WatchSetWatchdogModeUnlocked(unsigned int id, WATCHDOGMODE mode) { auto obj = watchexpr.find(id); if(obj != watchexpr.end()) obj->second->setWatchdogMode(mode); } void WatchSetWatchdogMode(unsigned int id, WATCHDOGMODE mode) { EXCLUSIVE_ACQUIRE(LockWatch); WatchSetWatchdogModeUnlocked(id, mode); EXCLUSIVE_RELEASE(); GuiUpdateWatchViewAsync(); } WATCHDOGMODE WatchGetWatchdogEnabled(unsigned int id) { SHARED_ACQUIRE(LockWatch); auto obj = watchexpr.find(id); if(obj != watchexpr.end()) return obj->second->getWatchdogMode(); else return WATCHDOGMODE::MODE_DISABLED; } duint WatchGetUnsignedValue(unsigned int id) { EXCLUSIVE_ACQUIRE(LockWatch); auto obj = watchexpr.find(id); if(obj != watchexpr.end()) return obj->second->getIntValue(); else return 0; } WATCHVARTYPE WatchGetType(unsigned int id) { SHARED_ACQUIRE(LockWatch); auto obj = watchexpr.find(id); if(obj != watchexpr.end()) return obj->second->getType(); else return WATCHVARTYPE::TYPE_INVALID; } void WatchSetTypeUnlocked(unsigned int id, WATCHVARTYPE type) { auto obj = watchexpr.find(id); if(obj != watchexpr.end()) obj->second->setType(type); } void WatchSetType(unsigned int id, WATCHVARTYPE type) { EXCLUSIVE_ACQUIRE(LockWatch); WatchSetTypeUnlocked(id, type); EXCLUSIVE_RELEASE(); GuiUpdateWatchViewAsync(); } unsigned int WatchGetWindow(unsigned int id) { SHARED_ACQUIRE(LockWatch); auto obj = watchexpr.find(id); if(obj != watchexpr.end()) return obj->second->watchWindow; else return WATCHVARTYPE::TYPE_INVALID; } bool WatchIsWatchdogTriggered(unsigned int id) { SHARED_ACQUIRE(LockWatch); auto obj = watchexpr.find(id); if(obj != watchexpr.end()) return obj->second->watchdogTriggered; else return false; } void WatchSetWindow(unsigned int id, unsigned int window) { EXCLUSIVE_ACQUIRE(LockWatch); auto obj = watchexpr.find(id); if(obj != watchexpr.end()) obj->second->watchWindow = window; EXCLUSIVE_RELEASE(); GuiUpdateWatchViewAsync(); } std::vector<WATCHINFO> WatchGetList() { EXCLUSIVE_ACQUIRE(LockWatch); std::vector<WATCHINFO> watchList; for(auto & i : watchexpr) { WATCHINFO info; info.value = i.second->getCurrIntValue(); strcpy_s(info.WatchName, i.second->getName()); strcpy_s(info.Expression, i.second->getExpr().c_str()); info.varType = i.second->getType(); info.id = i.first; info.watchdogMode = i.second->getWatchdogMode(); info.watchdogTriggered = i.second->watchdogTriggered; info.window = i.second->watchWindow; watchList.push_back(info); } return watchList; } // Initialize id counter so that it begin with a unused value void WatchInitIdCounter() { idCounter = 1; for(auto i : watchexpr) if(i.first > idCounter) idCounter = i.first + 1; } void WatchCacheSave(JSON root) { EXCLUSIVE_ACQUIRE(LockWatch); JSON watchroot = json_array(); for(auto i : watchexpr) { if(i.second->getType() == WATCHVARTYPE::TYPE_INVALID) continue; JSON watchitem = json_object(); json_object_set_new(watchitem, "Expression", json_string(i.second->getExpr().c_str())); json_object_set_new(watchitem, "Name", json_string(i.second->getName())); switch(i.second->getType()) { case WATCHVARTYPE::TYPE_INT: json_object_set_new(watchitem, "DataType", json_string("int")); break; case WATCHVARTYPE::TYPE_UINT: json_object_set_new(watchitem, "DataType", json_string("uint")); break; case WATCHVARTYPE::TYPE_FLOAT: json_object_set_new(watchitem, "DataType", json_string("float")); break; case WATCHVARTYPE::TYPE_ASCII: json_object_set_new(watchitem, "DataType", json_string("ascii")); break; case WATCHVARTYPE::TYPE_UNICODE: json_object_set_new(watchitem, "DataType", json_string("unicode")); break; default: break; } switch(i.second->getWatchdogMode()) { case WATCHDOGMODE::MODE_DISABLED: json_object_set_new(watchitem, "WatchdogMode", json_string("Disabled")); break; case WATCHDOGMODE::MODE_CHANGED: json_object_set_new(watchitem, "WatchdogMode", json_string("Changed")); break; case WATCHDOGMODE::MODE_UNCHANGED: json_object_set_new(watchitem, "WatchdogMode", json_string("Unchanged")); break; case WATCHDOGMODE::MODE_ISTRUE: json_object_set_new(watchitem, "WatchdogMode", json_string("IsTrue")); break; case WATCHDOGMODE::MODE_ISFALSE: json_object_set_new(watchitem, "WatchdogMode", json_string("IsFalse")); break; default: break; } json_array_append_new(watchroot, watchitem); } if(json_array_size(watchroot)) json_object_set(root, "watch", watchroot); json_decref(watchroot); } void WatchCacheLoad(JSON root) { EXCLUSIVE_ACQUIRE(LockWatch); JSON watchroot = json_object_get(root, "watch"); if(!watchroot) watchroot = json_object_get(root, "Watch"); unsigned int i; JSON val; if(!watchroot) return; json_array_foreach(watchroot, i, val) { const char* expr = json_string_value(json_object_get(val, "Expression")); if(!expr) continue; const char* datatype = json_string_value(json_object_get(val, "DataType")); if(!datatype) datatype = "uint"; const char* WatchdogMode = json_string_value(json_object_get(val, "WatchdogMode")); if(!WatchdogMode) WatchdogMode = "Disabled"; const char* watchname = json_string_value(json_object_get(val, "Name")); if(!watchname) watchname = "Watch"; WATCHVARTYPE varType; WATCHDOGMODE watchdog_mode; if(strcmp(datatype, "int") == 0) varType = WATCHVARTYPE::TYPE_INT; else if(strcmp(datatype, "uint") == 0) varType = WATCHVARTYPE::TYPE_UINT; else if(strcmp(datatype, "float") == 0) varType = WATCHVARTYPE::TYPE_FLOAT; else if(strcmp(datatype, "ascii") == 0) varType = WATCHVARTYPE::TYPE_ASCII; else if(strcmp(datatype, "unicode") == 0) varType = WATCHVARTYPE::TYPE_UNICODE; else continue; if(strcmp(WatchdogMode, "Disabled") == 0) watchdog_mode = WATCHDOGMODE::MODE_DISABLED; else if(strcmp(WatchdogMode, "Changed") == 0) watchdog_mode = WATCHDOGMODE::MODE_CHANGED; else if(strcmp(WatchdogMode, "Unchanged") == 0) watchdog_mode = WATCHDOGMODE::MODE_UNCHANGED; else if(strcmp(WatchdogMode, "IsTrue") == 0) watchdog_mode = WATCHDOGMODE::MODE_ISTRUE; else if(strcmp(WatchdogMode, "IsFalse") == 0) watchdog_mode = WATCHDOGMODE::MODE_ISFALSE; else continue; unsigned int id = WatchAddExprUnlocked(expr, varType); WatchModifyNameUnlocked(id, watchname); WatchSetWatchdogModeUnlocked(id, watchdog_mode); } WatchInitIdCounter(); // Initialize id counter so that it begin with a unused value }