DWORD WINAPI scriptRunSync(void* arg) { int destline = (int)(duint)arg; if(!destline || destline > (int)linemap.size()) //invalid line destline = 0; if(destline) { destline = scriptinternalstep(destline - 1); //no breakpoints on non-executable locations if(!scriptinternalbpget(destline)) //no breakpoint set scriptinternalbptoggle(destline); } bAbort = false; if(scriptIp) scriptIp--; scriptIp = scriptinternalstep(scriptIp); bool bContinue = true; bool bIgnoreTimeout = settingboolget("Engine", "NoScriptTimeout"); unsigned long long kernelTime, userTime; FILETIME creationTime, exitTime; // unused while(bContinue && !bAbort) //run loop { bContinue = scriptinternalcmd(); if(scriptIp == scriptinternalstep(scriptIp)) //end of script { bContinue = false; scriptIp = scriptinternalstep(0); } if(bContinue) scriptIp = scriptinternalstep(scriptIp); //this is the next ip if(scriptinternalbpget(scriptIp)) //breakpoint=stop run loop bContinue = false; if(bContinue && !bIgnoreTimeout && GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, reinterpret_cast<LPFILETIME>(&kernelTime), reinterpret_cast<LPFILETIME>(&userTime)) != 0) { if(userTime + kernelTime >= 10 * 10000000) // time out in 10 seconds of CPU time { if(GuiScriptMsgyn(GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "The script is too busy. Would you like to terminate it now?"))) != 0) { dputs(QT_TRANSLATE_NOOP("DBG", "Script is terminated by user.")); break; } else bIgnoreTimeout = true; } } } bIsRunning = false; //not running anymore GuiScriptSetIp(scriptIp); return 0; }
//database functions void dbsave() { dprintf("Saving database..."); DWORD ticks = GetTickCount(); JSON root = json_object(); CommentCacheSave(root); LabelCacheSave(root); BookmarkCacheSave(root); FunctionCacheSave(root); LoopCacheSave(root); BpCacheSave(root); WString wdbpath = StringUtils::Utf8ToUtf16(dbpath); if(json_object_size(root)) { Handle hFile = CreateFileW(wdbpath.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); if(!hFile) { dputs("\nFailed to open database for writing!"); json_decref(root); //free root return; } SetEndOfFile(hFile); char* jsonText = json_dumps(root, JSON_INDENT(4)); DWORD written = 0; if(!WriteFile(hFile, jsonText, (DWORD)strlen(jsonText), &written, 0)) { json_free(jsonText); dputs("\nFailed to write database file!"); json_decref(root); //free root return; } hFile.Close(); json_free(jsonText); if(!settingboolget("Engine", "DisableDatabaseCompression")) LZ4_compress_fileW(wdbpath.c_str(), wdbpath.c_str()); } else //remove database when nothing is in there DeleteFileW(wdbpath.c_str()); dprintf("%ums\n", GetTickCount() - ticks); json_decref(root); //free root }
//database functions void dbsave() { dprintf("saving database..."); DWORD ticks = GetTickCount(); JSON root = json_object(); CommentCacheSave(root); LabelCacheSave(root); BookmarkCacheSave(root); FunctionCacheSave(root); LoopCacheSave(root); BpCacheSave(root); WString wdbpath = StringUtils::Utf8ToUtf16(dbpath); if(json_object_size(root)) { FILE* jsonFile = 0; if(_wfopen_s(&jsonFile, wdbpath.c_str(), L"wb")) { dputs("failed to open database file for editing!"); json_decref(root); //free root return; } if(json_dumpf(root, jsonFile, JSON_INDENT(4)) == -1) { dputs("couldn't write JSON to database file..."); json_decref(root); //free root return; } fclose(jsonFile); if(!settingboolget("Engine", "DisableCompression")) LZ4_compress_fileW(wdbpath.c_str(), wdbpath.c_str()); } else //remove database when nothing is in there DeleteFileW(wdbpath.c_str()); dprintf("%ums\n", GetTickCount() - ticks); json_decref(root); //free root }
void dbload() { // If the file doesn't exist, there is no DB to load if(!FileExists(dbpath)) return; dprintf("Loading database..."); DWORD ticks = GetTickCount(); // Multi-byte (UTF8) file path converted to UTF16 WString databasePathW = StringUtils::Utf8ToUtf16(dbpath); // Decompress the file if compression was enabled bool useCompression = !settingboolget("Engine", "DisableCompression"); LZ4_STATUS lzmaStatus = LZ4_INVALID_ARCHIVE; { lzmaStatus = LZ4_decompress_fileW(databasePathW.c_str(), databasePathW.c_str()); // Check return code if(useCompression && lzmaStatus != LZ4_SUCCESS && lzmaStatus != LZ4_INVALID_ARCHIVE) { dputs("\nInvalid database file!"); return; } } // Open the file for reading by the JSON parser FILE* jsonFile = nullptr; long jsonFileSize = 0; if(_wfopen_s(&jsonFile, databasePathW.c_str(), L"rb")) { dputs("\nFailed to open database file!"); return; } // Get the current file size fseek(jsonFile, 0, SEEK_END); jsonFileSize = ftell(jsonFile); fseek(jsonFile, 0, SEEK_SET); // Verify that the file size is greater than 0. // This corrects a bug when a file exists, but there is no data inside. JSON root = nullptr; if(jsonFileSize > 0) root = json_loadf(jsonFile, 0, 0); // Release the file handle and re-compress fclose(jsonFile); if(lzmaStatus != LZ4_INVALID_ARCHIVE && useCompression) LZ4_compress_fileW(databasePathW.c_str(), databasePathW.c_str()); // Validate JSON load status if(!root) { dputs("\nInvalid database file (JSON)!"); return; } // Finally load all structures CommentCacheLoad(root); LabelCacheLoad(root); BookmarkCacheLoad(root); FunctionCacheLoad(root); LoopCacheLoad(root); BpCacheLoad(root); // Free root json_decref(root); dprintf("%ums\n", GetTickCount() - ticks); }
void dbload() { // If the file doesn't exist, there is no DB to load if(!FileExists(dbpath)) return; dprintf("Loading database..."); DWORD ticks = GetTickCount(); // Multi-byte (UTF8) file path converted to UTF16 WString databasePathW = StringUtils::Utf8ToUtf16(dbpath); // Decompress the file if compression was enabled bool useCompression = !settingboolget("Engine", "DisableDatabaseCompression"); LZ4_STATUS lzmaStatus = LZ4_INVALID_ARCHIVE; { lzmaStatus = LZ4_decompress_fileW(databasePathW.c_str(), databasePathW.c_str()); // Check return code if(useCompression && lzmaStatus != LZ4_SUCCESS && lzmaStatus != LZ4_INVALID_ARCHIVE) { dputs("\nInvalid database file!"); return; } } // Read the database file Handle hFile = CreateFileW(databasePathW.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if(!hFile) { dputs("\nFailed to open database file!"); return; } unsigned int jsonFileSize = GetFileSize(hFile, 0); if(!jsonFileSize) { dputs("\nEmpty database file!"); return; } Memory<char*> jsonText(jsonFileSize + 1); DWORD read = 0; if(!ReadFile(hFile, jsonText(), jsonFileSize, &read, 0)) { dputs("\nFailed to read database file!"); return; } hFile.Close(); // Deserialize JSON JSON root = json_loads(jsonText(), 0, 0); if(lzmaStatus != LZ4_INVALID_ARCHIVE && useCompression) LZ4_compress_fileW(databasePathW.c_str(), databasePathW.c_str()); // Validate JSON load status if(!root) { dputs("\nInvalid database file (JSON)!"); return; } // Finally load all structures CommentCacheLoad(root); LabelCacheLoad(root); BookmarkCacheLoad(root); FunctionCacheLoad(root); LoopCacheLoad(root); BpCacheLoad(root); // Free root json_decref(root); dprintf("%ums\n", GetTickCount() - ticks); }
extern "C" DLL_EXPORT uint _dbg_sendmessage(DBGMSG type, void* param1, void* param2) { if(dbgisstopped()) { switch(type) //ignore win events { //these functions are safe to call when we did not initialize yet case DBG_DEINITIALIZE_LOCKS: case DBG_INITIALIZE_LOCKS: case DBG_GET_FUNCTIONS: case DBG_SETTINGS_UPDATED: case DBG_GET_THREAD_LIST: case DBG_WIN_EVENT: case DBG_WIN_EVENT_GLOBAL: break; //the rest is unsafe -> throw an exception when people try to call them default: __debugbreak(); //we cannot process messages when the debugger is stopped, this must be a bug } } switch(type) { case DBG_SCRIPT_LOAD: { scriptload((const char*)param1); } break; case DBG_SCRIPT_UNLOAD: { scriptunload(); } break; case DBG_SCRIPT_RUN: { scriptrun((int)(duint)param1); } break; case DBG_SCRIPT_STEP: { scriptstep(); } break; case DBG_SCRIPT_BPTOGGLE: { return scriptbptoggle((int)(duint)param1); } break; case DBG_SCRIPT_BPGET: { return scriptbpget((int)(duint)param1); } break; case DBG_SCRIPT_CMDEXEC: { return scriptcmdexec((const char*)param1); } break; case DBG_SCRIPT_ABORT: { scriptabort(); } break; case DBG_SCRIPT_GETLINETYPE: { return (duint)scriptgetlinetype((int)(duint)param1); } break; case DBG_SCRIPT_SETIP: { scriptsetip((int)(duint)param1); } break; case DBG_SCRIPT_GETBRANCHINFO: { return (duint)scriptgetbranchinfo((int)(duint)param1, (SCRIPTBRANCH*)param2); } break; case DBG_SYMBOL_ENUM: { SYMBOLCBINFO* cbInfo = (SYMBOLCBINFO*)param1; SymEnum(cbInfo->base, cbInfo->cbSymbolEnum, cbInfo->user); } break; case DBG_ASSEMBLE_AT: { return assembleat((duint)param1, (const char*)param2, 0, 0, false); } break; case DBG_MODBASE_FROM_NAME: { return ModBaseFromName((const char*)param1); } break; case DBG_DISASM_AT: { disasmget((uint)param1, (DISASM_INSTR*)param2); } break; case DBG_STACK_COMMENT_GET: { return stackcommentget((uint)param1, (STACK_COMMENT*)param2); } break; case DBG_GET_THREAD_LIST: { ThreadGetList((THREADLIST*)param1); } break; case DBG_SETTINGS_UPDATED: { valuesetsignedcalc(!settingboolget("Engine", "CalculationType")); //0:signed, 1:unsigned SetEngineVariable(UE_ENGINE_SET_DEBUG_PRIVILEGE, settingboolget("Engine", "EnableDebugPrivilege")); bOnlyCipAutoComments = settingboolget("Disassembler", "OnlyCipAutoComments"); bListAllPages = settingboolget("Engine", "ListAllPages"); bUndecorateSymbolNames = settingboolget("Engine", "UndecorateSymbolNames"); bEnableSourceDebugging = settingboolget("Engine", "EnableSourceDebugging"); uint setting; if(BridgeSettingGetUint("Engine", "BreakpointType", &setting)) { switch(setting) { case 0: //break_int3short SetBPXOptions(UE_BREAKPOINT_INT3); break; case 1: //break_int3long SetBPXOptions(UE_BREAKPOINT_LONG_INT3); break; case 2: //break_ud2 SetBPXOptions(UE_BREAKPOINT_UD2); break; } } char exceptionRange[MAX_SETTING_SIZE] = ""; dbgclearignoredexceptions(); if(BridgeSettingGet("Exceptions", "IgnoreRange", exceptionRange)) { char* entry = strtok(exceptionRange, ","); while(entry) { unsigned long start; unsigned long end; if(sscanf(entry, "%08X-%08X", &start, &end) == 2 && start <= end) { ExceptionRange range; range.start = start; range.end = end; dbgaddignoredexception(range); } entry = strtok(0, ","); } } char cachePath[MAX_SETTING_SIZE]; if(BridgeSettingGet("Symbols", "CachePath", cachePath)) { // Trim the buffer to fit inside MAX_PATH strncpy_s(szSymbolCachePath, cachePath, _TRUNCATE); } } break; case DBG_DISASM_FAST_AT: { if(!param1 || !param2) return 0; BASIC_INSTRUCTION_INFO* basicinfo = (BASIC_INSTRUCTION_INFO*)param2; if(!disasmfast((uint)param1, basicinfo)) basicinfo->size = 1; return 0; } break; case DBG_MENU_ENTRY_CLICKED: { int hEntry = (int)(uint)param1; pluginmenucall(hEntry); } break; case DBG_FUNCTION_GET: { FUNCTION_LOOP_INFO* info = (FUNCTION_LOOP_INFO*)param1; return (uint)FunctionGet(info->addr, &info->start, &info->end); } break; case DBG_FUNCTION_OVERLAPS: { FUNCTION_LOOP_INFO* info = (FUNCTION_LOOP_INFO*)param1; return (uint)FunctionOverlaps(info->start, info->end); } break; case DBG_FUNCTION_ADD: { FUNCTION_LOOP_INFO* info = (FUNCTION_LOOP_INFO*)param1; return (uint)FunctionAdd(info->start, info->end, info->manual); } break; case DBG_FUNCTION_DEL: { FUNCTION_LOOP_INFO* info = (FUNCTION_LOOP_INFO*)param1; return (uint)FunctionDelete(info->addr); } break; case DBG_LOOP_GET: { FUNCTION_LOOP_INFO* info = (FUNCTION_LOOP_INFO*)param1; return (uint)LoopGet(info->depth, info->addr, &info->start, &info->end); } break; case DBG_LOOP_OVERLAPS: { FUNCTION_LOOP_INFO* info = (FUNCTION_LOOP_INFO*)param1; return (uint)LoopOverlaps(info->depth, info->start, info->end, 0); } break; case DBG_LOOP_ADD: { FUNCTION_LOOP_INFO* info = (FUNCTION_LOOP_INFO*)param1; return (uint)LoopAdd(info->start, info->end, info->manual); } break; case DBG_LOOP_DEL: { FUNCTION_LOOP_INFO* info = (FUNCTION_LOOP_INFO*)param1; return (uint)LoopDelete(info->depth, info->addr); } break; case DBG_IS_RUN_LOCKED: { return (uint)waitislocked(WAITID_RUN); } break; case DBG_IS_BP_DISABLED: { BREAKPOINT bp; if(BpGet((uint)param1, BPNORMAL, 0, &bp)) return !(uint)bp.enabled; return (uint)false; } break; case DBG_SET_AUTO_COMMENT_AT: { return (uint)CommentSet((uint)param1, (const char*)param2, false); } break; case DBG_DELETE_AUTO_COMMENT_RANGE: { CommentDelRange((uint)param1, (uint)param2); } break; case DBG_SET_AUTO_LABEL_AT: { return (uint)LabelSet((uint)param1, (const char*)param2, false); } break; case DBG_DELETE_AUTO_LABEL_RANGE: { LabelDelRange((uint)param1, (uint)param2); } break; case DBG_SET_AUTO_BOOKMARK_AT: { return (uint)BookmarkSet((uint)param1, false); } break; case DBG_DELETE_AUTO_BOOKMARK_RANGE: { BookmarkDelRange((uint)param1, (uint)param2); } break; case DBG_SET_AUTO_FUNCTION_AT: { return (uint)FunctionAdd((uint)param1, (uint)param2, false); } break; case DBG_DELETE_AUTO_FUNCTION_RANGE: { FunctionDelRange((uint)param1, (uint)param2); } break; case DBG_GET_STRING_AT: { STRING_TYPE strtype; char string[MAX_STRING_SIZE]; if(disasmgetstringat((uint)param1, &strtype, string, string, MAX_STRING_SIZE-3)) { if(strtype == str_ascii) sprintf((char*)param2, "\"%s\"", string); else //unicode sprintf((char*)param2, "L\"%s\"", string); return true; } return false; } break; case DBG_GET_FUNCTIONS: { return (uint)dbgfunctionsget(); } break; case DBG_WIN_EVENT: { return (uint)pluginwinevent((MSG*)param1, (long*)param2); } break; case DBG_WIN_EVENT_GLOBAL: { return (uint)pluginwineventglobal((MSG*)param1); } break; case DBG_INITIALIZE_LOCKS: { SectionLockerGlobal::Initialize(); } break; case DBG_DEINITIALIZE_LOCKS: { SectionLockerGlobal::Deinitialize(); } break; case DBG_GET_TIME_WASTED_COUNTER: return dbggettimewastedcounter(); } return 0; }