/
githubmirror
/
x64dbg
Обзор
Документация
Войти
/
githubmirror
/
x64dbg
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
development
src/dbg/commands/cmd-gui.cpp
392 строки
11 KB
Duncan Ogilvie
Fix bug in graph where 'Sync with RIP' would always re-analyze
16 июл 2026, 19:42
16 июл 2026, 19:42
213fb14
Код
Авторство
О чём код?
#include "cmd-gui.h" #include "debugger.h" #include "console.h" #include "memory.h" #include "recursiveanalysis.h" #include "function.h" #include "module.h" #include "stringformat.h" #include "value.h" #include "variable.h" bool cbShowThreadId(int argc, char* argv[]) { if(argc > 1) { duint threadId = 0; if(!valfromstring(argv[1], &threadId, false)) return false; SELECTIONDATA newSelection = { threadId, threadId }; if(!GuiSelectionSet(GUI_THREADS, &newSelection)) { dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid thread %s\n"), formatpidtid((DWORD)threadId).c_str()); return false; } } GuiShowThreads(); return true; } bool cbDebugDisasm(int argc, char* argv[]) { duint addr = 0; if(argc > 1) { if(!valfromstring(argv[1], &addr)) addr = GetContextDataEx(hActiveThread, UE_CIP); } else { addr = GetContextDataEx(hActiveThread, UE_CIP); } DebugUpdateGui(addr, false); GuiShowCpu(); GuiFocusView(GUI_DISASSEMBLY); return true; } bool cbDebugDump(int argc, char* argv[]) { if(IsArgumentsLessThan(argc, 2)) return false; duint addr = 0; if(!valfromstring(argv[1], &addr)) { dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid address \"%s\"!\n"), argv[1]); return false; } if(argc > 2) { duint index = 0; if(!valfromstring(argv[2], &index)) { dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid address \"%s\"!\n"), argv[2]); return false; } GuiDumpAtN(addr, int(index)); } else { ACTIVEVIEW activeView; GuiGetActiveView(&activeView); int dumpIndex; if(sscanf_s(activeView.title, "Dump %d", &dumpIndex) == 1) GuiDumpAtN(addr, dumpIndex); else GuiDumpAt(addr); } GuiShowCpu(); GuiFocusView(GUI_DUMP); return true; } bool cbDebugStackDump(int argc, char* argv[]) { duint addr = 0; if(argc < 2) addr = GetContextDataEx(hActiveThread, UE_CSP); else if(!valfromstring(argv[1], &addr)) { dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid address \"%s\"!\n"), argv[1]); return false; } duint csp = GetContextDataEx(hActiveThread, UE_CSP); duint size = 0; duint base = MemFindBaseAddr(csp, &size); if(base && addr >= base && addr < (base + size)) DebugUpdateStack(addr, csp, true); else dputs(QT_TRANSLATE_NOOP("DBG", "Invalid stack address!")); GuiShowCpu(); GuiFocusView(GUI_STACK); return true; } bool cbDebugMemmapdump(int argc, char* argv[]) { if(argc < 2) return false; duint addr; if(!valfromstring(argv[1], &addr, false) || !MemIsValidReadPtr(addr, true)) { dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid address \"%s\"!\n"), argv[1]); return false; } GuiSelectInMemoryMap(addr); GuiFocusView(GUI_MEMMAP); return true; } bool cbInstrGraph(int argc, char* argv[]) { auto options = argc > 2 ? argv[2] : ""; auto forceRefresh = !!strstr(options, "force"); auto silent = !!strstr(options, "silent"); duint userSelection = 0; if(argc < 2 || !valfromstring(argv[1], &userSelection)) userSelection = GetContextDataEx(hActiveThread, UE_CIP); // Find (heuristic) function entry point from user selection (0 if it cannot be determined) const auto functionEntry = std::invoke([userSelection] { duint start = 0; if(FunctionGet(userSelection, &start)) return start; return ModFunctionEntryGuessFromAddr(userSelection); }); // Navigate to user selection in the current graph, get cached graph entry point const auto cachedEntry = GuiGraphAt(userSelection); // Reuse the cached graph when the selection is inside it, unless the selection // confidently belongs to a different function entry const auto cacheInvalidated = cachedEntry == 0 || (functionEntry != 0 && cachedEntry != functionEntry); // Rebuild the graph from the function entry, falling back to the cached entry // (relevant for a forced refresh) and finally the user selection const auto graphEntry = functionEntry != 0 ? functionEntry : (cachedEntry != 0 ? cachedEntry : userSelection); // Make sure the address is valid duint size = 0; auto base = MemFindBaseAddr(graphEntry, &size); if(!base || !MemIsValidReadPtr(graphEntry)) { if(!silent) dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid address %p!\n"), graphEntry); return false; } if(forceRefresh || cacheInvalidated) { const auto modbase = ModBaseFromAddr(base); if(modbase != 0) { base = modbase; size = ModSizeFromAddr(modbase); } RecursiveAnalysis analysis(base, size, graphEntry, true); analysis.Analyse(); auto graph = analysis.GetFunctionGraph(graphEntry); if(graph == nullptr) { if(!silent) dputs(QT_TRANSLATE_NOOP("DBG", "No graph generated...")); return false; } auto graphList = graph->ToGraphList(); if(!GuiLoadGraph(&graphList, userSelection)) return false; } GuiUpdateAllViews(); if(!silent) GuiFocusView(GUI_GRAPH); return true; } bool cbInstrEnableGuiUpdate(int argc, char* argv[]) { if(GuiIsUpdateDisabled()) GuiUpdateEnable(false); duint value; //argv[1]=="1" = update GUI if(argc > 1 && valfromstring(argv[1], &value) && value == 1) GuiUpdateAllViews(); return true; } bool cbInstrDisableGuiUpdate(int argc, char* argv[]) { if(!GuiIsUpdateDisabled()) GuiUpdateDisable(); return true; } bool cbDebugSetfreezestack(int argc, char* argv[]) { if(IsArgumentsLessThan(argc, 2)) return false; bool freeze = *argv[1] != '0'; dbgsetfreezestack(freeze); if(freeze) dputs(QT_TRANSLATE_NOOP("DBG", "Stack is now frozen\n")); else dputs(QT_TRANSLATE_NOOP("DBG", "Stack is now unfrozen\n")); return true; } static bool bRefinit = false; bool cbInstrRefinit(int argc, char* argv[]) { auto title = argc > 1 ? stringformatinline(argv[1]) : GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Script")); GuiReferenceInitialize(title.c_str()); GuiReferenceAddColumn(sizeof(duint) * 2, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Address"))); GuiReferenceAddColumn(0, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Data"))); GuiReferenceSetRowCount(0); GuiReferenceReloadData(); bRefinit = true; return true; } bool cbInstrRefadd(int argc, char* argv[]) { if(IsArgumentsLessThan(argc, 3)) return false; duint addr = 0; if(!valfromstring(argv[1], &addr, false)) return false; if(!bRefinit) cbInstrRefinit(argc, argv); int index = GuiReferenceGetRowCount(); GuiReferenceSetRowCount(index + 1); char addr_text[32] = ""; sprintf_s(addr_text, "%p", (void*)addr); GuiReferenceSetCellContent(index, 0, addr_text); GuiReferenceSetCellContent(index, 1, stringformatinline(argv[2]).c_str()); GuiReferenceReloadData(); return true; } bool cbInstrRefGet(int argc, char* argv[]) { if(IsArgumentsLessThan(argc, 2)) return false; duint row; if(!valfromstring(argv[1], &row, false)) return false; auto content = GuiReferenceGetCellContent(int(row), 0); duint addr = 0; valfromstring(content, &addr, false); varset("$result", addr, false); BridgeFree(content); return true; } bool cbInstrEnableLog(int argc, char* argv[]) { GuiEnableLog(); return true; } bool cbInstrDisableLog(int argc, char* argv[]) { GuiDisableLog(); return true; } bool cbInstrAddFavTool(int argc, char* argv[]) { // filename, description if(IsArgumentsLessThan(argc, 2)) return false; if(argc == 2) GuiAddFavouriteTool(argv[1], nullptr); else GuiAddFavouriteTool(argv[1], argv[2]); return true; } bool cbInstrAddFavCmd(int argc, char* argv[]) { // command, shortcut if(IsArgumentsLessThan(argc, 2)) return false; if(argc == 2) GuiAddFavouriteCommand(argv[1], nullptr); else GuiAddFavouriteCommand(argv[1], argv[2]); return true; } bool cbInstrSetFavToolShortcut(int argc, char* argv[]) { // filename, shortcut if(IsArgumentsLessThan(argc, 3)) return false; GuiSetFavouriteToolShortcut(argv[1], argv[2]); return true; } bool cbInstrFoldDisassembly(int argc, char* argv[]) { if(IsArgumentsLessThan(argc, 3)) return false; duint start, length; if(!valfromstring(argv[1], &start)) { dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid argument 1 : %s\n"), argv[1]); return false; } if(!valfromstring(argv[2], &length)) { dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid argument 2 : %s\n"), argv[2]); return false; } GuiFoldDisassembly(start, length); return true; } bool cbDebugUpdateTitle(int argc, char* argv[]) { duint addr = 0; if(argc > 1) { if(!valfromstring(argv[1], &addr)) addr = GetContextDataEx(hActiveThread, UE_CIP); } else { addr = GetContextDataEx(hActiveThread, UE_CIP); } DebugUpdateTitleAsync(addr, false); return true; } bool cbShowReferences(int argc, char* argv[]) { GuiShowReferences(); return true; } bool cbSymbolsFollow(int argc, char* argv[]) { if(argc < 2) return false; duint addr; if(!valfromstring(argv[1], &addr, false) || !MemIsValidReadPtr(addr, true)) { dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid address \"%s\"!\n"), argv[1]); return false; } duint base = ModBaseFromAddr(addr); if(!base) { dprintf(QT_TRANSLATE_NOOP("DBG", "Address \"%s\" doesn't belong to any module!\n"), argv[1]); return false; } GuiSelectInSymbolsTab(base); GuiFocusView(GUI_SYMMOD); return true; } bool cbGotoTrace(int argc, char* argv[]) { duint index = 0; if(IsArgumentsLessThan(argc, 2) || !valfromstring(argv[1], &index, false)) return false; GuiGotoTrace(index); GuiShowTrace(); return true; }