/
githubmirror
/
x64dbg
Обзор
Документация
Войти
/
githubmirror
/
x64dbg
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
development
src/dbg/TraceRecord.h
122 строки
4 KB
Duncan Ogilvie
Flush trace recording when an exception is hit to not lose data
31 май 2026, 19:07
31 май 2026, 19:07
a8de10f
Код
Авторство
О чём код?
#ifndef TRACERECORD_H #define TRACERECORD_H #include "_global.h" #include "_dbgfunctions.h" #include "debugger.h" #include "jansson/jansson_x64dbg.h" #include <zydis_wrapper.h> class TraceRecordManager { public: enum TraceRecordByteType { InstructionBody = 0, InstructionHeading = 1, InstructionTailing = 2, InstructionOverlapped = 3, // The byte was executed with differing instruction base addresses Unknown = 4, DataByte, // This and the following is not implemented yet. DataWord, DataDWord, DataQWord, DataFloat, DataDouble, DataLongDouble, DataXMM, DataYMM, DataMMX, DataMixed, //the byte is accessed in multiple ways InstructionDataMixed //the byte is both executed and written }; /*************************************************************** * Trace record data layout * TraceRecordNonoe: disable trace record * TraceRecordBitExec: single-bit, executed. * TraceRecordByteWithExecTypeAndCounter: 8-bit, YYXXXXXX YY:=TraceRecordByteType_2bit, XXXXXX:=Hit count(6bit) * TraceRecordWordWithExecTypeAndCounter: 16-bit, YYXXXXXX XXXXXXXX YY:=TraceRecordByteType_2bit, XX:=Hit count(14bit) * Other: reserved for future expanding **************************************************************/ enum TraceRecordType { TraceRecordNone, TraceRecordBitExec, TraceRecordByteWithExecTypeAndCounter, TraceRecordWordWithExecTypeAndCounter }; TraceRecordManager(); ~TraceRecordManager(); void clear(); bool setTraceRecordType(duint pageAddress, TraceRecordType type); TraceRecordType getTraceRecordType(duint pageAddress); void TraceExecute(duint address, duint size); //void TraceAccess(duint address, unsigned char size, TraceRecordByteType accessType); void TraceExecuteRecord(const Zydis & newInstruction); void FlushTraceExecuteRecord(); unsigned int getHitCount(duint address); TraceRecordByteType getByteType(duint address); void increaseInstructionCounter(); bool isTraceRecordingEnabled(); bool enableTraceRecording(bool enabled, const char* fileName); void saveToDb(JSON root); void loadFromDb(JSON root); private: // An enumerated value indicating this byte is either start of instruction, middle of instruction, end of instruction, or part of overlapped instruction. enum TraceRecordByteType_2bit { _InstructionBody = 0, _InstructionHeading = 1, _InstructionTailing = 2, _InstructionOverlapped = 3, _Unknown = 4 // Never recorded, unknown }; struct TraceRecordPage { void* rawPtr; duint rva; TraceRecordType dataType; unsigned int moduleIndex; }; typedef union _REGDUMPWORD { REGDUMP registers; // 172 qwords on x64, 216 dwords on x86. Almost no space left for AVX512 // strip off lastStatus and 128 bytes of lastError.name member. duint regword[(FIELD_OFFSET(REGDUMP, lastError) + sizeof(DWORD)) / sizeof(duint)]; } REGDUMPWORD; //Key := page base, value := trace record raw data std::unordered_map<duint, TraceRecordPage> TraceRecord; std::vector<std::string> ModuleNames; unsigned int getModuleIndex(const String & moduleName); unsigned int instructionCounter = 0; bool rtEnabled = false; bool rtPrevInstAvailable = false; HANDLE rtFile = nullptr; REGDUMPWORD rtOldContext; bool rtOldContextChanged[(FIELD_OFFSET(REGDUMP, lastError) + sizeof(DWORD)) / sizeof(duint)]; DWORD rtOldThreadId; bool rtNeedThreadId; duint rtOldMemory[32]; duint rtOldMemoryAddress[32]; char rtOldOpcode[16]; unsigned int rtRecordedInstructions; unsigned char rtOldOpcodeSize; unsigned char rtOldMemoryArrayCount; }; extern TraceRecordManager TraceRecord; void dbgtraceexecute(duint CIP); #endif // TRACERECORD_H