diff --git a/BrachTraceExe/BrachTraceExe.vcxproj b/BrachTraceExe/BrachTraceExe.vcxproj
new file mode 100644
index 0000000..1bdaca2
--- /dev/null
+++ b/BrachTraceExe/BrachTraceExe.vcxproj
@@ -0,0 +1,150 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ {8D95F0D0-2975-4A8B-9499-317C50E55264}
+ BrachTraceExe
+ 10.0
+
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ MultiThreadedDebug
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ MultiThreadedDebug
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ MultiThreaded
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BrachTraceExe/BrachTraceExe.vcxproj.filters b/BrachTraceExe/BrachTraceExe.vcxproj.filters
new file mode 100644
index 0000000..93b404b
--- /dev/null
+++ b/BrachTraceExe/BrachTraceExe.vcxproj.filters
@@ -0,0 +1,22 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/BrachTraceExe/BrachTraceExe.vcxproj.user b/BrachTraceExe/BrachTraceExe.vcxproj.user
new file mode 100644
index 0000000..cb74406
--- /dev/null
+++ b/BrachTraceExe/BrachTraceExe.vcxproj.user
@@ -0,0 +1,27 @@
+
+
+
+ WindowsRemoteDebugger
+ $(TargetPath)
+ 192.168.3.7
+ RemoteWithoutAuthentication
+
+
+ $(TargetPath)
+ WindowsRemoteDebugger
+ 192.168.3.7
+ RemoteWithoutAuthentication
+
+
+ $(TargetPath)
+ WindowsRemoteDebugger
+ 192.168.3.7
+ RemoteWithoutAuthentication
+
+
+ $(TargetPath)
+ WindowsRemoteDebugger
+ 192.168.3.7
+ RemoteWithoutAuthentication
+
+
\ No newline at end of file
diff --git a/BrachTraceExe/brach-trace-exe.cpp b/BrachTraceExe/brach-trace-exe.cpp
new file mode 100644
index 0000000..de721ed
--- /dev/null
+++ b/BrachTraceExe/brach-trace-exe.cpp
@@ -0,0 +1,87 @@
+#include
+#include "..\BranchTracerSys\ioctls.h"
+#include
+
+
+
+typedef struct _BTS_RECORD64
+{
+ ULONG64 from; // ¼Ç¼·ÖÖ§µÄÔ´µØÖ·
+ ULONG64 to; // ¼Ç¼·ÖÖ§µÄÄ¿±êµØÖ·
+ ULONG64 branchPredicted;
+}BTS_RECORD64, * PBTS_RECORD64;
+
+
+
+int main() {
+ HANDLE hDevice = CreateFileA("\\\\.\\Branch-Trace", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+
+ ULONG ThreadId = 0;
+ printf("Enter thread id:");
+ scanf_s("%d", &ThreadId);
+
+ START_THREAD_TRACE_PARAM StartRequest = { 0 };
+ StartRequest.ThreadId = ThreadId;
+
+ DWORD BytesReturned = 0;
+ if (!DeviceIoControl(hDevice, IOCTL_START_THREAD_TRACE,
+ (LPVOID)&StartRequest, sizeof(StartRequest),
+ (LPVOID)&StartRequest, sizeof(StartRequest),
+ &BytesReturned, NULL))
+ {
+ printf("Start Trace failed!\n");
+ return -1;
+ }
+
+ printf("Press Enter to conttinue\n");
+ system("pause");
+
+#define BIFFER_SIZE 0x2000
+ PVOID Buffer = VirtualAlloc(NULL, BIFFER_SIZE, MEM_COMMIT, PAGE_READWRITE);
+ STOP_THREAD_TRACE_PARAM StopRequest = { 0 };
+ StopRequest.ThreadId = ThreadId;
+ StopRequest.Buffer = Buffer;
+ StopRequest.BufferSize = BIFFER_SIZE;
+ StopRequest.FilterStart = 0x00400000;
+ StopRequest.FilterEnd = 0x00D4C000+0x4000;
+
+
+ if (!DeviceIoControl(hDevice, IOCTL_STOP_THREAD_TRACE,
+ (LPVOID)&StopRequest, sizeof(StopRequest),
+ (LPVOID)&StopRequest, sizeof(StopRequest),
+ &BytesReturned, NULL))
+ {
+ printf("Stop Trace failed!\n");
+ getchar();
+ return -1;
+ }
+
+ printf("Successful Buffer:%p ReadSize:%x\n", StopRequest.Buffer, StopRequest.ReadSize);
+
+
+ PBTS_RECORD64 RecordStart = (PBTS_RECORD64)Buffer;
+ PBTS_RECORD64 RecordEnd = (PBTS_RECORD64)((ULONG_PTR)Buffer + StopRequest.ReadSize);
+
+
+ // ÄæÅÅ, ´ÓÇý¶¯À»ØÀ´µÄ¼Ç¼˳Ðò¸úÖ´ÐÐ˳ÐòµÄÏà·´.
+ for (PBTS_RECORD64 p1 = RecordStart, p2 = RecordEnd - 1;
+ p1 < p2;
+ p1++, p2--)
+ {
+ BTS_RECORD64 temp = *p1;
+ *p1 = *p2;
+ *p2 = temp;
+ }
+
+ PBTS_RECORD64 pRecord = RecordStart;
+ while (pRecord < RecordEnd)
+ {
+ printf("%llx-> %llx\n", pRecord->from, pRecord->to);
+ pRecord++;
+ }
+
+ system("pause");
+ getchar();
+
+
+}
\ No newline at end of file
diff --git a/BranchTrace-x64plugin-wtl/BranchTrace-x64plugin-wtl.aps b/BranchTrace-x64plugin-wtl/BranchTrace-x64plugin-wtl.aps
new file mode 100644
index 0000000..1a98d2e
Binary files /dev/null and b/BranchTrace-x64plugin-wtl/BranchTrace-x64plugin-wtl.aps differ
diff --git a/BranchTrace-x64plugin-wtl/BranchTrace-x64plugin-wtl.rc b/BranchTrace-x64plugin-wtl/BranchTrace-x64plugin-wtl.rc
new file mode 100644
index 0000000..45ba1aa
--- /dev/null
+++ b/BranchTrace-x64plugin-wtl/BranchTrace-x64plugin-wtl.rc
@@ -0,0 +1,133 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Chinese (Simplified, PRC) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
+#pragma code_page(936)
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// PNG
+//
+
+IDB_PNG_THREAD PNG "res\\Thread.png"
+
+IDB_PNG_TRACE PNG "res\\trace.png"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DIALOG_THREAD_TRACE DIALOGEX 0, 0, 319, 232
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Thread Trace"
+FONT 8, "Consolas", 400, 0, 0x0
+BEGIN
+ COMBOBOX IDC_COMBO_THREAD,72,14,180,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Start Trace",IDC_BUTTON_STARTTRACE,257,14,55,14
+ PUSHBUTTON "Reset",IDC_BUTTON_RESET,257,32,55,14,WS_DISABLED
+ LTEXT "Choose Thread",IDC_STATIC,14,17,53,8
+ PUSHBUTTON "Prev",IDC_BUTTON_PREV,257,169,55,14,WS_DISABLED
+ PUSHBUTTON "Next(Into)",IDC_BUTTON_NEXTINTO,257,67,55,14,WS_DISABLED
+ PUSHBUTTON "Prev(Into)",IDC_BUTTON_PREVINTO,257,51,55,14,WS_DISABLED
+ PUSHBUTTON "&Next",IDC_BUTTON_NEXT,257,185,55,14,WS_DISABLED
+ LTEXT "Choose Module",IDC_STATIC,14,34,53,8
+ COMBOBOX IDC_COMBO_MODULE,72,32,180,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,14,51,238,174
+ PUSHBUTTON "ProcStart",IDC_BUTTON_PROCSTART,257,91,55,14,WS_DISABLED
+ PUSHBUTTON "ProcEnd",IDC_BUTTON_PROCEND,257,107,55,14,WS_DISABLED
+ PUSHBUTTON "ToEnd",IDC_BUTTON_TOEND,257,211,55,14,WS_DISABLED
+ PUSHBUTTON "Prev Snippet",IDC_BUTTON_PREVSNIPPET,257,130,55,14,WS_DISABLED
+ PUSHBUTTON "Next Snippet",IDC_BUTTON_NEXTSNIPPET,257,146,55,14,WS_DISABLED
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_DIALOG_THREAD_TRACE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 312
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 225
+ HORZGUIDE, 22
+ HORZGUIDE, 38
+ HORZGUIDE, 51
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// AFX_DIALOG_LAYOUT
+//
+
+IDD_DIALOG_THREAD_TRACE AFX_DIALOG_LAYOUT
+BEGIN
+ 0
+END
+
+#endif // Chinese (Simplified, PRC) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/BranchTrace-x64plugin-wtl/BranchTrace-x64plugin-wtl.vcxproj b/BranchTrace-x64plugin-wtl/BranchTrace-x64plugin-wtl.vcxproj
new file mode 100644
index 0000000..d543592
--- /dev/null
+++ b/BranchTrace-x64plugin-wtl/BranchTrace-x64plugin-wtl.vcxproj
@@ -0,0 +1,219 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {e29237f6-bf51-4b3c-a9a7-5c988650686e}
+ BranchTracex64pluginwtl
+ 10.0
+
+
+
+ DynamicLibrary
+ true
+ v142
+ MultiByte
+
+
+ DynamicLibrary
+ false
+ v142
+ true
+ MultiByte
+
+
+ DynamicLibrary
+ true
+ v142
+ MultiByte
+
+
+ DynamicLibrary
+ false
+ v142
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ .dp$(PlatformArchitecture)
+ ..\..\..\x64dbg_plugins\x64dbg\x$(PlatformArchitecture)\plugins
+ $(IncludePath);E:\third-lib\includes;
+
+
+ false
+ .dp$(PlatformArchitecture)
+ ..\..\..\x64dbg_plugins\x64dbg\x$(PlatformArchitecture)\plugins
+ $(IncludePath);E:\third-lib\includes;
+
+
+ true
+ .dp$(PlatformArchitecture)
+ ..\..\..\x64dbg_plugins\x64dbg\x$(PlatformArchitecture)\plugins
+ $(IncludePath);E:\third-lib\includes;
+
+
+ false
+ .dp$(PlatformArchitecture)
+ ..\..\..\x64dbg_plugins\x64dbg\x$(PlatformArchitecture)\plugins
+ $(IncludePath);E:\third-lib\includes;
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ MultiThreadedDebug
+
+
+ NotSet
+ true
+ kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);E:\third-lib\lib\$(Configuration)$(PlatformTarget)\Zydis.lib
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ MultiThreaded
+
+
+ NotSet
+ true
+ true
+ true
+ kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);E:\third-lib\lib\$(Configuration)$(PlatformTarget)\Zydis.lib;
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ MultiThreadedDebug
+
+
+ NotSet
+ true
+ kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);E:\third-lib\lib\$(Configuration)$(PlatformTarget)\Zydis.lib;
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ MultiThreaded
+
+
+ NotSet
+ true
+ true
+ true
+ kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);E:\third-lib\lib\$(Configuration)$(PlatformTarget)\Zydis.lib;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BranchTrace-x64plugin-wtl/BranchTrace-x64plugin-wtl.vcxproj.filters b/BranchTrace-x64plugin-wtl/BranchTrace-x64plugin-wtl.vcxproj.filters
new file mode 100644
index 0000000..c4b729a
--- /dev/null
+++ b/BranchTrace-x64plugin-wtl/BranchTrace-x64plugin-wtl.vcxproj.filters
@@ -0,0 +1,177 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+ {2e430117-686d-4410-a80c-cdc92ba350af}
+
+
+ {631d739d-396f-4d5d-b3e3-2cdae72c6524}
+
+
+ {f01f3db0-bd30-466f-a1af-f05619d18cb9}
+
+
+ {7191814d-618e-4bb6-b06e-999c73fa2915}
+
+
+ {f443bc61-3a33-4dfa-9385-e1cd6fabc425}
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files\ThreadTrace
+
+
+ Source Files\disassembler
+
+
+ Source Files\LDasm
+
+
+ Source Files\ThreadTrace
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Header Files
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Source Files\ThreadTrace
+
+
+ Source Files
+
+
+ Header Files
+
+
+ Source Files\ThreadTrace
+
+
+ Source Files\disassembler
+
+
+ Source Files\LDasm
+
+
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+ Header Files\pluginsdk
+
+
+
+
+ Resource Files
+
+
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+
\ No newline at end of file
diff --git a/BranchTrace-x64plugin-wtl/BranchTrace-x64plugin-wtl.vcxproj.user b/BranchTrace-x64plugin-wtl/BranchTrace-x64plugin-wtl.vcxproj.user
new file mode 100644
index 0000000..2e019c4
--- /dev/null
+++ b/BranchTrace-x64plugin-wtl/BranchTrace-x64plugin-wtl.vcxproj.user
@@ -0,0 +1,38 @@
+
+
+
+ E:\Projects\x64dbg_plugins\x64dbg\x$(PlatformArchitecture)\x$(PlatformArchitecture)dbg.exe
+ WindowsRemoteDebugger
+ E:\Projects\x64dbg_plugins\x64dbg\x$(PlatformArchitecture)\x$(PlatformArchitecture)dbg.exe
+ 192.168.3.7
+ RemoteWithoutAuthentication
+ E:\Projects\x64dbg_plugins\x64dbg\x$(PlatformArchitecture)
+
+
+ E:\Projects\x64dbg_plugins\x64dbg\x$(PlatformArchitecture)\x$(PlatformArchitecture)dbg.exe
+ WindowsRemoteDebugger
+ E:\Projects\x64dbg_plugins\x64dbg\x$(PlatformArchitecture)\x$(PlatformArchitecture)dbg.exe
+ 192.168.3.7
+ RemoteWithoutAuthentication
+ E:\Projects\x64dbg_plugins\x64dbg\x$(PlatformArchitecture)
+
+
+ E:\Projects\x64dbg_plugins\x64dbg\x$(PlatformArchitecture)\x$(PlatformArchitecture)dbg.exe
+ WindowsRemoteDebugger
+ E:\Projects\x64dbg_plugins\x64dbg\x$(PlatformArchitecture)\x$(PlatformArchitecture)dbg.exe
+ E:\Projects\x64dbg_plugins\x64dbg\x$(PlatformArchitecture)
+ 192.168.3.7
+ RemoteWithoutAuthentication
+
+
+ E:\Projects\x64dbg_plugins\x64dbg\x$(PlatformArchitecture)\x$(PlatformArchitecture)dbg.exe
+ WindowsRemoteDebugger
+ E:\Projects\x64dbg_plugins\x64dbg\x$(PlatformArchitecture)\x$(PlatformArchitecture)dbg.exe
+ E:\Projects\x64dbg_plugins\x64dbg\x$(PlatformArchitecture)
+ 192.168.3.7
+ RemoteWithoutAuthentication
+
+
+ BranchTrace-x64plugin-wtl.rc
+
+
\ No newline at end of file
diff --git a/BranchTrace-x64plugin-wtl/LDasm/LDasm.c b/BranchTrace-x64plugin-wtl/LDasm/LDasm.c
new file mode 100644
index 0000000..8d91e51
--- /dev/null
+++ b/BranchTrace-x64plugin-wtl/LDasm/LDasm.c
@@ -0,0 +1,863 @@
+/*
+*
+* Copyright (c) 2009-2011
+* vol4ok PGP KEY ID: 26EC143CCDC61C9D
+*
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+
+*/
+
+#include "LDasm.h"
+
+/*
+ Instruction format:
+
+ | prefix | REX | opcode | modR/M | SIB | disp8/16/32 | imm8/16/32/64 |
+
+ */
+
+#define OP_NONE 0x00
+#define OP_INVALID 0x80
+
+#define OP_DATA_I8 0x01
+#define OP_DATA_I16 0x02
+#define OP_DATA_I16_I32 0x04
+#define OP_DATA_I16_I32_I64 0x08
+#define OP_EXTENDED 0x10
+#define OP_RELATIVE 0x20
+#define OP_MODRM 0x40
+#define OP_PREFIX 0x80
+
+
+static unsigned char flags_table[256] =
+{
+ /* 00 */ OP_MODRM,
+ /* 01 */ OP_MODRM,
+ /* 02 */ OP_MODRM,
+ /* 03 */ OP_MODRM,
+ /* 04 */ OP_DATA_I8,
+ /* 05 */ OP_DATA_I16_I32,
+ /* 06 */ OP_NONE,
+ /* 07 */ OP_NONE,
+ /* 08 */ OP_MODRM,
+ /* 09 */ OP_MODRM,
+ /* 0A */ OP_MODRM,
+ /* 0B */ OP_MODRM,
+ /* 0C */ OP_DATA_I8,
+ /* 0D */ OP_DATA_I16_I32,
+ /* 0E */ OP_NONE,
+ /* 0F */ OP_NONE,
+
+ /* 10 */ OP_MODRM,
+ /* 11 */ OP_MODRM,
+ /* 12 */ OP_MODRM,
+ /* 13 */ OP_MODRM,
+ /* 14 */ OP_DATA_I8,
+ /* 15 */ OP_DATA_I16_I32,
+ /* 16 */ OP_NONE,
+ /* 17 */ OP_NONE,
+ /* 18 */ OP_MODRM,
+ /* 19 */ OP_MODRM,
+ /* 1A */ OP_MODRM,
+ /* 1B */ OP_MODRM,
+ /* 1C */ OP_DATA_I8,
+ /* 1D */ OP_DATA_I16_I32,
+ /* 1E */ OP_NONE,
+ /* 1F */ OP_NONE,
+
+ /* 20 */ OP_MODRM,
+ /* 21 */ OP_MODRM,
+ /* 22 */ OP_MODRM,
+ /* 23 */ OP_MODRM,
+ /* 24 */ OP_DATA_I8,
+ /* 25 */ OP_DATA_I16_I32,
+ /* 26 */ OP_PREFIX,
+ /* 27 */ OP_NONE,
+ /* 28 */ OP_MODRM,
+ /* 29 */ OP_MODRM,
+ /* 2A */ OP_MODRM,
+ /* 2B */ OP_MODRM,
+ /* 2C */ OP_DATA_I8,
+ /* 2D */ OP_DATA_I16_I32,
+ /* 2E */ OP_PREFIX,
+ /* 2F */ OP_NONE,
+
+ /* 30 */ OP_MODRM,
+ /* 31 */ OP_MODRM,
+ /* 32 */ OP_MODRM,
+ /* 33 */ OP_MODRM,
+ /* 34 */ OP_DATA_I8,
+ /* 35 */ OP_DATA_I16_I32,
+ /* 36 */ OP_PREFIX,
+ /* 37 */ OP_NONE,
+ /* 38 */ OP_MODRM,
+ /* 39 */ OP_MODRM,
+ /* 3A */ OP_MODRM,
+ /* 3B */ OP_MODRM,
+ /* 3C */ OP_DATA_I8,
+ /* 3D */ OP_DATA_I16_I32,
+ /* 3E */ OP_PREFIX,
+ /* 3F */ OP_NONE,
+
+ /* 40 */ OP_NONE,
+ /* 41 */ OP_NONE,
+ /* 42 */ OP_NONE,
+ /* 43 */ OP_NONE,
+ /* 44 */ OP_NONE,
+ /* 45 */ OP_NONE,
+ /* 46 */ OP_NONE,
+ /* 47 */ OP_NONE,
+ /* 48 */ OP_NONE,
+ /* 49 */ OP_NONE,
+ /* 4A */ OP_NONE,
+ /* 4B */ OP_NONE,
+ /* 4C */ OP_NONE,
+ /* 4D */ OP_NONE,
+ /* 4E */ OP_NONE,
+ /* 4F */ OP_NONE,
+
+ /* 50 */ OP_NONE,
+ /* 51 */ OP_NONE,
+ /* 52 */ OP_NONE,
+ /* 53 */ OP_NONE,
+ /* 54 */ OP_NONE,
+ /* 55 */ OP_NONE,
+ /* 56 */ OP_NONE,
+ /* 57 */ OP_NONE,
+ /* 58 */ OP_NONE,
+ /* 59 */ OP_NONE,
+ /* 5A */ OP_NONE,
+ /* 5B */ OP_NONE,
+ /* 5C */ OP_NONE,
+ /* 5D */ OP_NONE,
+ /* 5E */ OP_NONE,
+ /* 5F */ OP_NONE,
+ /* 60 */ OP_NONE,
+
+ /* 61 */ OP_NONE,
+ /* 62 */ OP_MODRM,
+ /* 63 */ OP_MODRM,
+ /* 64 */ OP_PREFIX,
+ /* 65 */ OP_PREFIX,
+ /* 66 */ OP_PREFIX,
+ /* 67 */ OP_PREFIX,
+ /* 68 */ OP_DATA_I16_I32,
+ /* 69 */ OP_MODRM | OP_DATA_I16_I32,
+ /* 6A */ OP_DATA_I8,
+ /* 6B */ OP_MODRM | OP_DATA_I8,
+ /* 6C */ OP_NONE,
+ /* 6D */ OP_NONE,
+ /* 6E */ OP_NONE,
+ /* 6F */ OP_NONE,
+
+ /* 70 */ OP_RELATIVE | OP_DATA_I8,
+ /* 71 */ OP_RELATIVE | OP_DATA_I8,
+ /* 72 */ OP_RELATIVE | OP_DATA_I8,
+ /* 73 */ OP_RELATIVE | OP_DATA_I8,
+ /* 74 */ OP_RELATIVE | OP_DATA_I8,
+ /* 75 */ OP_RELATIVE | OP_DATA_I8,
+ /* 76 */ OP_RELATIVE | OP_DATA_I8,
+ /* 77 */ OP_RELATIVE | OP_DATA_I8,
+ /* 78 */ OP_RELATIVE | OP_DATA_I8,
+ /* 79 */ OP_RELATIVE | OP_DATA_I8,
+ /* 7A */ OP_RELATIVE | OP_DATA_I8,
+ /* 7B */ OP_RELATIVE | OP_DATA_I8,
+ /* 7C */ OP_RELATIVE | OP_DATA_I8,
+ /* 7D */ OP_RELATIVE | OP_DATA_I8,
+ /* 7E */ OP_RELATIVE | OP_DATA_I8,
+ /* 7F */ OP_RELATIVE | OP_DATA_I8,
+
+ /* 80 */ OP_MODRM | OP_DATA_I8,
+ /* 81 */ OP_MODRM | OP_DATA_I16_I32,
+ /* 82 */ OP_MODRM | OP_DATA_I8,
+ /* 83 */ OP_MODRM | OP_DATA_I8,
+ /* 84 */ OP_MODRM,
+ /* 85 */ OP_MODRM,
+ /* 86 */ OP_MODRM,
+ /* 87 */ OP_MODRM,
+ /* 88 */ OP_MODRM,
+ /* 89 */ OP_MODRM,
+ /* 8A */ OP_MODRM,
+ /* 8B */ OP_MODRM,
+ /* 8C */ OP_MODRM,
+ /* 8D */ OP_MODRM,
+ /* 8E */ OP_MODRM,
+ /* 8F */ OP_MODRM,
+
+ /* 90 */ OP_NONE,
+ /* 91 */ OP_NONE,
+ /* 92 */ OP_NONE,
+ /* 93 */ OP_NONE,
+ /* 94 */ OP_NONE,
+ /* 95 */ OP_NONE,
+ /* 96 */ OP_NONE,
+ /* 97 */ OP_NONE,
+ /* 98 */ OP_NONE,
+ /* 99 */ OP_NONE,
+ /* 9A */ OP_DATA_I16 | OP_DATA_I16_I32,
+ /* 9B */ OP_NONE,
+ /* 9C */ OP_NONE,
+ /* 9D */ OP_NONE,
+ /* 9E */ OP_NONE,
+ /* 9F */ OP_NONE,
+
+ /* A0 */ OP_DATA_I8,
+ /* A1 */ OP_DATA_I16_I32_I64,
+ /* A2 */ OP_DATA_I8,
+ /* A3 */ OP_DATA_I16_I32_I64,
+ /* A4 */ OP_NONE,
+ /* A5 */ OP_NONE,
+ /* A6 */ OP_NONE,
+ /* A7 */ OP_NONE,
+ /* A8 */ OP_DATA_I8,
+ /* A9 */ OP_DATA_I16_I32,
+ /* AA */ OP_NONE,
+ /* AB */ OP_NONE,
+ /* AC */ OP_NONE,
+ /* AD */ OP_NONE,
+ /* AE */ OP_NONE,
+ /* AF */ OP_NONE,
+
+ /* B0 */ OP_DATA_I8,
+ /* B1 */ OP_DATA_I8,
+ /* B2 */ OP_DATA_I8,
+ /* B3 */ OP_DATA_I8,
+ /* B4 */ OP_DATA_I8,
+ /* B5 */ OP_DATA_I8,
+ /* B6 */ OP_DATA_I8,
+ /* B7 */ OP_DATA_I8,
+ /* B8 */ OP_DATA_I16_I32_I64,
+ /* B9 */ OP_DATA_I16_I32_I64,
+ /* BA */ OP_DATA_I16_I32_I64,
+ /* BB */ OP_DATA_I16_I32_I64,
+ /* BC */ OP_DATA_I16_I32_I64,
+ /* BD */ OP_DATA_I16_I32_I64,
+ /* BE */ OP_DATA_I16_I32_I64,
+ /* BF */ OP_DATA_I16_I32_I64,
+
+ /* C0 */ OP_MODRM | OP_DATA_I8,
+ /* C1 */ OP_MODRM | OP_DATA_I8,
+ /* C2 */ OP_DATA_I16,
+ /* C3 */ OP_NONE,
+ /* C4 */ OP_MODRM,
+ /* C5 */ OP_MODRM,
+ /* C6 */ OP_MODRM | OP_DATA_I8,
+ /* C7 */ OP_MODRM | OP_DATA_I16_I32,
+ /* C8 */ OP_DATA_I8 | OP_DATA_I16,
+ /* C9 */ OP_NONE,
+ /* CA */ OP_DATA_I16,
+ /* CB */ OP_NONE,
+ /* CC */ OP_NONE,
+ /* CD */ OP_DATA_I8,
+ /* CE */ OP_NONE,
+ /* CF */ OP_NONE,
+
+ /* D0 */ OP_MODRM,
+ /* D1 */ OP_MODRM,
+ /* D2 */ OP_MODRM,
+ /* D3 */ OP_MODRM,
+ /* D4 */ OP_DATA_I8,
+ /* D5 */ OP_DATA_I8,
+ /* D6 */ OP_NONE,
+ /* D7 */ OP_NONE,
+ /* D8 */ OP_MODRM,
+ /* D9 */ OP_MODRM,
+ /* DA */ OP_MODRM,
+ /* DB */ OP_MODRM,
+ /* DC */ OP_MODRM,
+ /* DD */ OP_MODRM,
+ /* DE */ OP_MODRM,
+ /* DF */ OP_MODRM,
+
+ /* E0 */ OP_RELATIVE | OP_DATA_I8,
+ /* E1 */ OP_RELATIVE | OP_DATA_I8,
+ /* E2 */ OP_RELATIVE | OP_DATA_I8,
+ /* E3 */ OP_RELATIVE | OP_DATA_I8,
+ /* E4 */ OP_DATA_I8,
+ /* E5 */ OP_DATA_I8,
+ /* E6 */ OP_DATA_I8,
+ /* E7 */ OP_DATA_I8,
+ /* E8 */ OP_RELATIVE | OP_DATA_I16_I32,
+ /* E9 */ OP_RELATIVE | OP_DATA_I16_I32,
+ /* EA */ OP_DATA_I16 | OP_DATA_I16_I32,
+ /* EB */ OP_RELATIVE | OP_DATA_I8,
+ /* EC */ OP_NONE,
+ /* ED */ OP_NONE,
+ /* EE */ OP_NONE,
+ /* EF */ OP_NONE,
+
+ /* F0 */ OP_PREFIX,
+ /* F1 */ OP_NONE,
+ /* F2 */ OP_PREFIX,
+ /* F3 */ OP_PREFIX,
+ /* F4 */ OP_NONE,
+ /* F5 */ OP_NONE,
+ /* F6 */ OP_MODRM,
+ /* F7 */ OP_MODRM,
+ /* F8 */ OP_NONE,
+ /* F9 */ OP_NONE,
+ /* FA */ OP_NONE,
+ /* FB */ OP_NONE,
+ /* FC */ OP_NONE,
+ /* FD */ OP_NONE,
+ /* FE */ OP_MODRM,
+ /* FF */ OP_MODRM
+};
+
+static unsigned char flags_table_ex[256] =
+{
+ /* 0F00 */ OP_MODRM,
+ /* 0F01 */ OP_MODRM,
+ /* 0F02 */ OP_MODRM,
+ /* 0F03 */ OP_MODRM,
+ /* 0F04 */ OP_INVALID,
+ /* 0F05 */ OP_NONE,
+ /* 0F06 */ OP_NONE,
+ /* 0F07 */ OP_NONE,
+ /* 0F08 */ OP_NONE,
+ /* 0F09 */ OP_NONE,
+ /* 0F0A */ OP_INVALID,
+ /* 0F0B */ OP_NONE,
+ /* 0F0C */ OP_INVALID,
+ /* 0F0D */ OP_MODRM,
+ /* 0F0E */ OP_INVALID,
+ /* 0F0F */ OP_MODRM | OP_DATA_I8, //3Dnow
+
+ /* 0F10 */ OP_MODRM,
+ /* 0F11 */ OP_MODRM,
+ /* 0F12 */ OP_MODRM,
+ /* 0F13 */ OP_MODRM,
+ /* 0F14 */ OP_MODRM,
+ /* 0F15 */ OP_MODRM,
+ /* 0F16 */ OP_MODRM,
+ /* 0F17 */ OP_MODRM,
+ /* 0F18 */ OP_MODRM,
+ /* 0F19 */ OP_INVALID,
+ /* 0F1A */ OP_INVALID,
+ /* 0F1B */ OP_INVALID,
+ /* 0F1C */ OP_INVALID,
+ /* 0F1D */ OP_INVALID,
+ /* 0F1E */ OP_INVALID,
+ /* 0F1F */ OP_NONE,
+
+ /* 0F20 */ OP_MODRM,
+ /* 0F21 */ OP_MODRM,
+ /* 0F22 */ OP_MODRM,
+ /* 0F23 */ OP_MODRM,
+ /* 0F24 */ OP_MODRM | OP_EXTENDED, //SSE5
+ /* 0F25 */ OP_INVALID,
+ /* 0F26 */ OP_MODRM,
+ /* 0F27 */ OP_INVALID,
+ /* 0F28 */ OP_MODRM,
+ /* 0F29 */ OP_MODRM,
+ /* 0F2A */ OP_MODRM,
+ /* 0F2B */ OP_MODRM,
+ /* 0F2C */ OP_MODRM,
+ /* 0F2D */ OP_MODRM,
+ /* 0F2E */ OP_MODRM,
+ /* 0F2F */ OP_MODRM,
+
+ /* 0F30 */ OP_NONE,
+ /* 0F31 */ OP_NONE,
+ /* 0F32 */ OP_NONE,
+ /* 0F33 */ OP_NONE,
+ /* 0F34 */ OP_NONE,
+ /* 0F35 */ OP_NONE,
+ /* 0F36 */ OP_INVALID,
+ /* 0F37 */ OP_NONE,
+ /* 0F38 */ OP_MODRM | OP_EXTENDED,
+ /* 0F39 */ OP_INVALID,
+ /* 0F3A */ OP_MODRM | OP_EXTENDED | OP_DATA_I8,
+ /* 0F3B */ OP_INVALID,
+ /* 0F3C */ OP_INVALID,
+ /* 0F3D */ OP_INVALID,
+ /* 0F3E */ OP_INVALID,
+ /* 0F3F */ OP_INVALID,
+
+ /* 0F40 */ OP_MODRM,
+ /* 0F41 */ OP_MODRM,
+ /* 0F42 */ OP_MODRM,
+ /* 0F43 */ OP_MODRM,
+ /* 0F44 */ OP_MODRM,
+ /* 0F45 */ OP_MODRM,
+ /* 0F46 */ OP_MODRM,
+ /* 0F47 */ OP_MODRM,
+ /* 0F48 */ OP_MODRM,
+ /* 0F49 */ OP_MODRM,
+ /* 0F4A */ OP_MODRM,
+ /* 0F4B */ OP_MODRM,
+ /* 0F4C */ OP_MODRM,
+ /* 0F4D */ OP_MODRM,
+ /* 0F4E */ OP_MODRM,
+ /* 0F4F */ OP_MODRM,
+
+ /* 0F50 */ OP_MODRM,
+ /* 0F51 */ OP_MODRM,
+ /* 0F52 */ OP_MODRM,
+ /* 0F53 */ OP_MODRM,
+ /* 0F54 */ OP_MODRM,
+ /* 0F55 */ OP_MODRM,
+ /* 0F56 */ OP_MODRM,
+ /* 0F57 */ OP_MODRM,
+ /* 0F58 */ OP_MODRM,
+ /* 0F59 */ OP_MODRM,
+ /* 0F5A */ OP_MODRM,
+ /* 0F5B */ OP_MODRM,
+ /* 0F5C */ OP_MODRM,
+ /* 0F5D */ OP_MODRM,
+ /* 0F5E */ OP_MODRM,
+ /* 0F5F */ OP_MODRM,
+
+ /* 0F60 */ OP_MODRM,
+ /* 0F61 */ OP_MODRM,
+ /* 0F62 */ OP_MODRM,
+ /* 0F63 */ OP_MODRM,
+ /* 0F64 */ OP_MODRM,
+ /* 0F65 */ OP_MODRM,
+ /* 0F66 */ OP_MODRM,
+ /* 0F67 */ OP_MODRM,
+ /* 0F68 */ OP_MODRM,
+ /* 0F69 */ OP_MODRM,
+ /* 0F6A */ OP_MODRM,
+ /* 0F6B */ OP_MODRM,
+ /* 0F6C */ OP_MODRM,
+ /* 0F6D */ OP_MODRM,
+ /* 0F6E */ OP_MODRM,
+ /* 0F6F */ OP_MODRM,
+
+ /* 0F70 */ OP_MODRM | OP_DATA_I8,
+ /* 0F71 */ OP_MODRM | OP_DATA_I8,
+ /* 0F72 */ OP_MODRM | OP_DATA_I8,
+ /* 0F73 */ OP_MODRM | OP_DATA_I8,
+ /* 0F74 */ OP_MODRM,
+ /* 0F75 */ OP_MODRM,
+ /* 0F76 */ OP_MODRM,
+ /* 0F77 */ OP_NONE,
+ /* 0F78 */ OP_MODRM,
+ /* 0F79 */ OP_MODRM,
+ /* 0F7A */ OP_INVALID,
+ /* 0F7B */ OP_INVALID,
+ /* 0F7C */ OP_MODRM,
+ /* 0F7D */ OP_MODRM,
+ /* 0F7E */ OP_MODRM,
+ /* 0F7F */ OP_MODRM,
+
+ /* 0F80 */ OP_RELATIVE | OP_DATA_I16_I32,
+ /* 0F81 */ OP_RELATIVE | OP_DATA_I16_I32,
+ /* 0F82 */ OP_RELATIVE | OP_DATA_I16_I32,
+ /* 0F83 */ OP_RELATIVE | OP_DATA_I16_I32,
+ /* 0F84 */ OP_RELATIVE | OP_DATA_I16_I32,
+ /* 0F85 */ OP_RELATIVE | OP_DATA_I16_I32,
+ /* 0F86 */ OP_RELATIVE | OP_DATA_I16_I32,
+ /* 0F87 */ OP_RELATIVE | OP_DATA_I16_I32,
+ /* 0F88 */ OP_RELATIVE | OP_DATA_I16_I32,
+ /* 0F89 */ OP_RELATIVE | OP_DATA_I16_I32,
+ /* 0F8A */ OP_RELATIVE | OP_DATA_I16_I32,
+ /* 0F8B */ OP_RELATIVE | OP_DATA_I16_I32,
+ /* 0F8C */ OP_RELATIVE | OP_DATA_I16_I32,
+ /* 0F8D */ OP_RELATIVE | OP_DATA_I16_I32,
+ /* 0F8E */ OP_RELATIVE | OP_DATA_I16_I32,
+ /* 0F8F */ OP_RELATIVE | OP_DATA_I16_I32,
+
+ /* 0F90 */ OP_MODRM,
+ /* 0F91 */ OP_MODRM,
+ /* 0F92 */ OP_MODRM,
+ /* 0F93 */ OP_MODRM,
+ /* 0F94 */ OP_MODRM,
+ /* 0F95 */ OP_MODRM,
+ /* 0F96 */ OP_MODRM,
+ /* 0F97 */ OP_MODRM,
+ /* 0F98 */ OP_MODRM,
+ /* 0F99 */ OP_MODRM,
+ /* 0F9A */ OP_MODRM,
+ /* 0F9B */ OP_MODRM,
+ /* 0F9C */ OP_MODRM,
+ /* 0F9D */ OP_MODRM,
+ /* 0F9E */ OP_MODRM,
+ /* 0F9F */ OP_MODRM,
+
+ /* 0FA0 */ OP_NONE,
+ /* 0FA1 */ OP_NONE,
+ /* 0FA2 */ OP_NONE,
+ /* 0FA3 */ OP_MODRM,
+ /* 0FA4 */ OP_MODRM | OP_DATA_I8,
+ /* 0FA5 */ OP_MODRM,
+ /* 0FA6 */ OP_INVALID,
+ /* 0FA7 */ OP_INVALID,
+ /* 0FA8 */ OP_NONE,
+ /* 0FA9 */ OP_NONE,
+ /* 0FAA */ OP_NONE,
+ /* 0FAB */ OP_MODRM,
+ /* 0FAC */ OP_MODRM | OP_DATA_I8,
+ /* 0FAD */ OP_MODRM,
+ /* 0FAE */ OP_MODRM,
+ /* 0FAF */ OP_MODRM,
+
+ /* 0FB0 */ OP_MODRM,
+ /* 0FB1 */ OP_MODRM,
+ /* 0FB2 */ OP_MODRM,
+ /* 0FB3 */ OP_MODRM,
+ /* 0FB4 */ OP_MODRM,
+ /* 0FB5 */ OP_MODRM,
+ /* 0FB6 */ OP_MODRM,
+ /* 0FB7 */ OP_MODRM,
+ /* 0FB8 */ OP_MODRM,
+ /* 0FB9 */ OP_MODRM,
+ /* 0FBA */ OP_MODRM | OP_DATA_I8,
+ /* 0FBB */ OP_MODRM,
+ /* 0FBC */ OP_MODRM,
+ /* 0FBD */ OP_MODRM,
+ /* 0FBE */ OP_MODRM,
+ /* 0FBF */ OP_MODRM,
+
+ /* 0FC0 */ OP_MODRM,
+ /* 0FC1 */ OP_MODRM,
+ /* 0FC2 */ OP_MODRM | OP_DATA_I8,
+ /* 0FC3 */ OP_MODRM,
+ /* 0FC4 */ OP_MODRM | OP_DATA_I8,
+ /* 0FC5 */ OP_MODRM | OP_DATA_I8,
+ /* 0FC6 */ OP_MODRM | OP_DATA_I8,
+ /* 0FC7 */ OP_MODRM,
+ /* 0FC8 */ OP_NONE,
+ /* 0FC9 */ OP_NONE,
+ /* 0FCA */ OP_NONE,
+ /* 0FCB */ OP_NONE,
+ /* 0FCC */ OP_NONE,
+ /* 0FCD */ OP_NONE,
+ /* 0FCE */ OP_NONE,
+ /* 0FCF */ OP_NONE,
+
+ /* 0FD0 */ OP_MODRM,
+ /* 0FD1 */ OP_MODRM,
+ /* 0FD2 */ OP_MODRM,
+ /* 0FD3 */ OP_MODRM,
+ /* 0FD4 */ OP_MODRM,
+ /* 0FD5 */ OP_MODRM,
+ /* 0FD6 */ OP_MODRM,
+ /* 0FD7 */ OP_MODRM,
+ /* 0FD8 */ OP_MODRM,
+ /* 0FD9 */ OP_MODRM,
+ /* 0FDA */ OP_MODRM,
+ /* 0FDB */ OP_MODRM,
+ /* 0FDC */ OP_MODRM,
+ /* 0FDD */ OP_MODRM,
+ /* 0FDE */ OP_MODRM,
+ /* 0FDF */ OP_MODRM,
+
+ /* 0FE0 */ OP_MODRM,
+ /* 0FE1 */ OP_MODRM,
+ /* 0FE2 */ OP_MODRM,
+ /* 0FE3 */ OP_MODRM,
+ /* 0FE4 */ OP_MODRM,
+ /* 0FE5 */ OP_MODRM,
+ /* 0FE6 */ OP_MODRM,
+ /* 0FE7 */ OP_MODRM,
+ /* 0FE8 */ OP_MODRM,
+ /* 0FE9 */ OP_MODRM,
+ /* 0FEA */ OP_MODRM,
+ /* 0FEB */ OP_MODRM,
+ /* 0FEC */ OP_MODRM,
+ /* 0FED */ OP_MODRM,
+ /* 0FEE */ OP_MODRM,
+ /* 0FEF */ OP_MODRM,
+
+ /* 0FF0 */ OP_MODRM,
+ /* 0FF1 */ OP_MODRM,
+ /* 0FF2 */ OP_MODRM,
+ /* 0FF3 */ OP_MODRM,
+ /* 0FF4 */ OP_MODRM,
+ /* 0FF5 */ OP_MODRM,
+ /* 0FF6 */ OP_MODRM,
+ /* 0FF7 */ OP_MODRM,
+ /* 0FF8 */ OP_MODRM,
+ /* 0FF9 */ OP_MODRM,
+ /* 0FFA */ OP_MODRM,
+ /* 0FFB */ OP_MODRM,
+ /* 0FFC */ OP_MODRM,
+ /* 0FFD */ OP_MODRM,
+ /* 0FFE */ OP_MODRM,
+ /* 0FFF */ OP_INVALID,
+};
+
+unsigned char cflags(UINT8 op)
+{
+ return flags_table[op];
+}
+
+
+unsigned char cflags_ex(UINT8 op)
+{
+ return flags_table_ex[op];
+}
+
+unsigned int __fastcall PrevInstrLength(void* code, size_t bufferSize, UINT32 is64)
+{
+ void* buffer = malloc(bufferSize + 0x10);
+ if (buffer == NULL) {
+ return -1;
+ }
+ memset(buffer, 0x90, bufferSize + 0x10);
+ memcpy(buffer, code, bufferSize);
+
+ int length = 0;
+ ldasm_data ld;
+ for (size_t i = 0; i < bufferSize; i++)
+ {
+ int len = ldasm_length((char*)buffer + i, is64);
+ if (i+len == bufferSize) {
+ length = len;
+ }
+ }
+ free(buffer);
+ return length;
+}
+
+unsigned int __fastcall ldasm_length(void* code, UINT32 is64)
+{
+ ldasm_data ld;
+ return ldasm(code, &ld, 1);
+}
+
+unsigned int __fastcall ldasm(void* code, ldasm_data* ld, UINT32 is64)
+/*
+ Description:
+ Disassemble one instruction
+
+ Arguments:
+ code - pointer to the code for disassemble
+ ld - pointer to structure ldasm_data
+ is64 - set this flag for 64-bit code, and clear for 32-bit
+
+ Return:
+ length of instruction
+ */
+{
+ UINT8* p = (UINT8*)code;
+ UINT8 s, op, f;
+ UINT8 rexw, pr_66, pr_67;
+
+ s = rexw = pr_66 = pr_67 = 0;
+
+ /* dummy check */
+ if (!code || !ld)
+ return 0;
+
+ /* init output data */
+ memset(ld, 0, sizeof(ldasm_data));
+
+ /* phase 1: parse prefixies */
+ while (cflags(*p) & OP_PREFIX) {
+ if (*p == 0x66)
+ pr_66 = 1;
+ if (*p == 0x67)
+ pr_67 = 1;
+ p++;
+ s++;
+ ld->flags |= F_PREFIX;
+ if (s == 15) {
+ ld->flags |= F_INVALID;
+ return s;
+ }
+ }
+
+ /* parse REX prefix */
+ if (is64 && *p >> 4 == 4) {
+ ld->rex = *p;
+ rexw = (ld->rex >> 3) & 1;
+ ld->flags |= F_REX;
+ p++;
+ s++;
+ }
+
+ /* can be only one REX prefix */
+ if (is64 && *p >> 4 == 4) {
+ ld->flags |= F_INVALID;
+ s++;
+ return s;
+ }
+
+ /* phase 2: parse opcode */
+ ld->opcd_offset = (UINT8)(p - (UINT8*)code);
+ ld->opcd_size = 1;
+ op = *p++;
+ s++;
+
+ /* is 2 byte opcode? */
+ if (op == 0x0F) {
+ op = *p++;
+ s++;
+ ld->opcd_size++;
+ f = cflags_ex(op);
+ if (f & OP_INVALID) {
+ ld->flags |= F_INVALID;
+ return s;
+ }
+ /* for SSE instructions */
+ if (f & OP_EXTENDED) {
+ op = *p++;
+ s++;
+ ld->opcd_size++;
+ }
+ }
+ else {
+ f = cflags(op);
+ /* pr_66 = pr_67 for opcodes A0-A3 */
+ if (op >= 0xA0 && op <= 0xA3)
+ pr_66 = pr_67;
+ }
+
+ /* phase 3: parse ModR/M, SIB and DISP */
+ if (f & OP_MODRM) {
+ UINT8 mod = (*p >> 6);
+ UINT8 ro = (*p & 0x38) >> 3;
+ UINT8 rm = (*p & 7);
+
+ ld->modrm = *p++;
+ s++;
+ ld->flags |= F_MODRM;
+
+ /* in F6,F7 opcodes immediate data present if R/O == 0 */
+ if (op == 0xF6 && (ro == 0 || ro == 1))
+ f |= OP_DATA_I8;
+ if (op == 0xF7 && (ro == 0 || ro == 1))
+ f |= OP_DATA_I16_I32_I64;
+
+ /* is SIB byte exist? */
+ if (mod != 3 && rm == 4 && !(!is64 && pr_67)) {
+ ld->sib = *p++;
+ s++;
+ ld->flags |= F_SIB;
+
+ /* if base == 5 and mod == 0 */
+ if ((ld->sib & 7) == 5 && mod == 0) {
+ ld->disp_size = 4;
+ }
+ }
+
+ switch (mod) {
+ case 0:
+ if (is64) {
+ if (rm == 5) {
+ ld->disp_size = 4;
+ if (is64)
+ ld->flags |= F_RELATIVE;
+ }
+ }
+ else if (pr_67) {
+ if (rm == 6)
+ ld->disp_size = 2;
+ }
+ else {
+ if (rm == 5)
+ ld->disp_size = 4;
+ }
+ break;
+ case 1:
+ ld->disp_size = 1;
+ break;
+ case 2:
+ if (is64)
+ ld->disp_size = 4;
+ else if (pr_67)
+ ld->disp_size = 2;
+ else
+ ld->disp_size = 4;
+ break;
+ }
+
+ if (ld->disp_size) {
+ ld->disp_offset = (UINT8)(p - (UINT8*)code);
+ p += ld->disp_size;
+ s += ld->disp_size;
+ ld->flags |= F_DISP;
+ }
+ }
+
+ /* phase 4: parse immediate data */
+ if (rexw && f & OP_DATA_I16_I32_I64)
+ ld->imm_size = 8;
+ else if (f & OP_DATA_I16_I32 || f & OP_DATA_I16_I32_I64)
+ ld->imm_size = 4 - (pr_66 << 1);
+
+ /* if exist, add OP_DATA_I16 and OP_DATA_I8 size */
+ ld->imm_size += f & 3;
+
+ if (ld->imm_size) {
+ s += ld->imm_size;
+ ld->imm_offset = (UINT8)(p - (UINT8*)code);
+ ld->flags |= F_IMM;
+ if (f & OP_RELATIVE)
+ ld->flags |= F_RELATIVE;
+ }
+
+ /* instruction is too long */
+ if (s > 15)
+ ld->flags |= F_INVALID;
+
+ return s;
+}
+
+// Get function size
+unsigned long __fastcall SizeOfProc(void* Proc)
+{
+ UINT32 Length;
+ UINT8* pOpcode;
+ UINT32 Result = 0;
+ ldasm_data data = { 0 };
+
+ do {
+ Length = ldasm((UINT8*)Proc, &data, is_x64);
+
+ pOpcode = (UINT8*)Proc + data.opcd_offset;
+ Result += Length;
+
+ if (Length == 1) {
+ UCHAR opCode;
+ memcpy(&opCode, pOpcode, 1);
+ if (opCode == (UINT8)0xCC) {
+ break;
+ }
+ }
+
+ /*if ((Length == 1) && (*pOpcode == 0xC3))
+ break;
+
+ if ((Length == 3) && (*pOpcode == 0xC2))
+ break;*/
+
+ Proc = (void*)((size_t)Proc + Length);
+ } while (Length);
+
+ return Result;
+}
+
+// If function address is jmp - get jmp destination
+void* __fastcall ResolveJmp(void* Proc)
+{
+ UINT32 Length;
+ UINT8* pOpcode;
+ ldasm_data data = { 0 };
+
+ Length = ldasm((UINT8*)Proc, &data, is_x64);
+ pOpcode = (UINT8*)Proc + data.opcd_offset;
+
+ // Recursive unwind
+ if (Length == 5 && data.opcd_size == 1 && *pOpcode == 0xE9) {
+ UINT32 delta = *(INT32*)((uintptr_t)Proc + data.opcd_size);
+ return ResolveJmp((void*)((uintptr_t)Proc + delta + Length));
+ }
+
+ return Proc;
+}
diff --git a/BranchTrace-x64plugin-wtl/LDasm/LDasm.h b/BranchTrace-x64plugin-wtl/LDasm/LDasm.h
new file mode 100644
index 0000000..5514989
--- /dev/null
+++ b/BranchTrace-x64plugin-wtl/LDasm/LDasm.h
@@ -0,0 +1,51 @@
+#ifndef _LDASM_
+#define _LDASM_
+
+#include
+
+#ifdef _WIN64
+#define is_x64 1
+#else
+#define is_x64 0
+#endif//USE64
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define F_INVALID 0x01
+#define F_PREFIX 0x02
+#define F_REX 0x04
+#define F_MODRM 0x08
+#define F_SIB 0x10
+#define F_DISP 0x20
+#define F_IMM 0x40
+#define F_RELATIVE 0x80
+
+typedef struct _ldasm_data
+{
+ UINT8 flags;
+ UINT8 rex;
+ UINT8 modrm;
+ UINT8 sib;
+ UINT8 opcd_offset;
+ UINT8 opcd_size;
+ UINT8 disp_offset;
+ UINT8 disp_size;
+ UINT8 imm_offset;
+ UINT8 imm_size;
+} ldasm_data;
+
+
+unsigned int __fastcall ldasm_length(void* code, UINT32 is64);
+unsigned int __fastcall ldasm(void* code, ldasm_data* ld, UINT32 is64);
+unsigned long __fastcall SizeOfProc(void* Proc);
+unsigned int __fastcall PrevInstrLength(void* code, size_t bufferSize, UINT32 is64);
+void* __fastcall ResolveJmp(void* Proc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif//_LDASM_
diff --git a/BranchTrace-x64plugin-wtl/ThreadTraceCore.cpp b/BranchTrace-x64plugin-wtl/ThreadTraceCore.cpp
new file mode 100644
index 0000000..3de4cd5
--- /dev/null
+++ b/BranchTrace-x64plugin-wtl/ThreadTraceCore.cpp
@@ -0,0 +1,265 @@
+#include "ThreadTraceCore.h"
+#include
+
+
+
+bool StartTrace(DWORD ThreadId)
+{
+
+ HANDLE hDevice = CreateFileA("\\\\.\\Branch-Trace", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+
+ START_THREAD_TRACE_PARAM StartRequest = { 0 };
+ StartRequest.ThreadId = ThreadId;
+
+ DWORD BytesReturned = 0;
+ if (!DeviceIoControl(hDevice, IOCTL_START_THREAD_TRACE,
+ (LPVOID)&StartRequest, sizeof(StartRequest),
+ (LPVOID)&StartRequest, sizeof(StartRequest),
+ &BytesReturned, NULL))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool StopTrace()
+{
+ HANDLE hDevice = CreateFileA("\\\\.\\Branch-Trace", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if (hDevice == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+ DWORD BytesReturned = 0;
+ STOP_THREAD_TRACE_PARAM StopRequest = { 0 };
+ StopRequest.ThreadId = NULL;
+ StopRequest.Buffer = NULL;
+ StopRequest.BufferSize = 0;
+ StopRequest.FilterStart = 0;
+ StopRequest.FilterEnd = 0;
+
+ if (!DeviceIoControl(hDevice, IOCTL_STOP_THREAD_TRACE,
+ (LPVOID)&StopRequest, sizeof(StopRequest),
+ (LPVOID)&StopRequest, sizeof(StopRequest),
+ &BytesReturned, NULL))
+ {
+ CloseHandle(hDevice);
+ return false;
+ }
+
+ CloseHandle(hDevice);
+ return true;
+}
+
+bool StopAndFetchTrace(DWORD ThreadId, ULONG64 filterStart, ULONG64 fileterEnd, DWORD Records, PBTS_RECORD64* lpRecordStart, PBTS_RECORD64* lpRecordEnd)
+{
+ if (Records <= 0 || lpRecordStart == NULL || lpRecordEnd == NULL) {
+ return false;
+ }
+
+ HANDLE hDevice = CreateFileA("\\\\.\\Branch-Trace", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if (hDevice == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ DWORD bufferSize = Records * sizeof(BTS_RECORD64);
+ PVOID Buffer = VirtualAlloc(NULL, bufferSize, MEM_COMMIT, PAGE_READWRITE);
+ if (Buffer == NULL) {
+ CloseHandle(hDevice);
+ return false;
+ }
+
+ //STOP_THREAD_TRACE_PARAM StopRequest = { 0 };
+ //StopRequest.ThreadId = ThreadId;
+ //StopRequest.Buffer = Buffer;
+ //StopRequest.BufferSize = bufferSize;
+ //StopRequest.FilterStart = (ULONG64)filterStart;
+ //StopRequest.FilterEnd = (ULONG64)fileterEnd;
+
+ STOP_THREAD_TRACE_PARAM StopRequest = { 0 };
+ StopRequest.ThreadId = ThreadId;
+ StopRequest.Buffer = Buffer;
+ StopRequest.BufferSize = 0x2000;
+ StopRequest.FilterStart = 0x00400000;
+ StopRequest.FilterEnd = 0x00D4C000 + 0x4000;
+
+ DWORD BytesReturned = 0;
+ if (!DeviceIoControl(hDevice, IOCTL_STOP_THREAD_TRACE,
+ (LPVOID)&StopRequest, sizeof(StopRequest),
+ (LPVOID)&StopRequest, sizeof(StopRequest),
+ &BytesReturned, NULL))
+ {
+ VirtualFree(Buffer, 0, MEM_RELEASE);
+ CloseHandle(hDevice);
+ return false;
+ }
+
+ if (StopRequest.ReadSize == 0) {
+ VirtualFree(Buffer, 0, MEM_RELEASE);
+ CloseHandle(hDevice);
+ return false;
+ }
+
+
+ PBTS_RECORD64 RecordStart = (PBTS_RECORD64)Buffer;
+ PBTS_RECORD64 RecordEnd = (PBTS_RECORD64)((PUCHAR)Buffer + StopRequest.ReadSize);
+
+ // ÄæÅÅ
+ for (PBTS_RECORD64 p1 = RecordStart, p2 = RecordEnd - 1;
+ p1 < p2;
+ p1++, p2--)
+ {
+ BTS_RECORD64 temp = *p1;
+ *p1 = *p2;
+ *p2 = temp;
+ }
+
+
+
+ *lpRecordStart = RecordStart;
+ *lpRecordEnd = RecordEnd;
+
+ CloseHandle(hDevice);
+ return true;
+}
+
+bool TraceCursor::isAtTo()
+{
+ return pathIndex == 1;
+}
+
+bool TraceCursor::isAtFrom()
+{
+ return pathIndex == 0;
+}
+
+bool TraceCursor::toEndInstr()
+{
+ nodeIndex = nodes.size() - 1;
+ pathIndex = currentNode().paths.size() - 1;
+ return true;
+}
+
+bool TraceCursor::toPrevInstrInto()
+{
+ if (pathIndex > 0) {
+ pathIndex--;
+ return true;
+ }
+
+ if (nodeIndex > 0) {
+ nodeIndex--;
+ pathIndex = currentNode().paths.size() - 1;
+ return true;
+ }
+
+ return false;
+}
+
+bool TraceCursor::toNextInstrInto()
+{
+ if (pathIndex < currentNode().paths.size() - 1) {
+ pathIndex++;
+ return true;
+ }
+
+
+ //int pathSize = currentNode().paths.size();
+ //if (pathSize > 0 && pathIndex < pathSize - 1) {
+ // pathIndex++;
+ // return true;
+ //}
+
+ if (nodeIndex < nodes.size() - 1) {
+ nodeIndex++;
+ pathIndex = 0;
+ return true;
+ }
+
+ return false;
+
+ //int nodeSize = nodes.size();
+ //if (nodeSize > 0 && nodeIndex < nodeSize - 1)
+ //{
+ // nodeIndex++;
+ // pathIndex = 0;
+ // return true;
+ //}
+
+ //return false;
+}
+
+bool TraceCursor::toPrevInstr()
+{
+ if (pathIndex > 0) {
+ pathIndex--;
+ return true;
+ }
+
+ if (currentNode().hasPrev) {
+ nodeIndex = currentNode().prevIndex;
+ pathIndex = currentNode().paths.size() - 1;
+ return true;
+ }
+
+ //if (nodeIndex > 0)
+ //{
+ // nodeIndex--;
+ // pathIndex = currentNode().paths.size() - 1;
+ // return true;
+ //}
+
+ return false;
+}
+
+bool TraceCursor::toNextInstr()
+{
+ if (pathIndex < currentNode().paths.size() - 1) {
+ pathIndex++;
+ return true;
+ }
+
+ if (currentNode().hasNext) {
+ nodeIndex = currentNode().nextIndex;
+ pathIndex = 0;
+ return true;
+ }
+
+ return false;
+}
+
+bool TraceCursor::toProcStart()
+{
+ nodeIndex = currentNode().procStartIndex;
+ pathIndex = 0;
+ return true;
+}
+
+bool TraceCursor::toProcEnd()
+{
+ if (currentNode().procSubIndex.size() > 0) {
+ nodeIndex = currentNode().procSubIndex.back();
+ pathIndex = currentNode().paths.size() - 1;
+ return true;
+ }
+
+ return false;
+}
+
+bool TraceCursor::toProcPrevNode()
+{
+ if (currentNode().hasPrev) {
+ nodeIndex = currentNode().prevIndex;
+ }
+ pathIndex = 0;
+ return true;
+}
+
+bool TraceCursor::toProcNextNode()
+{
+ if (currentNode().hasNext) {
+ nodeIndex = currentNode().nextIndex;
+ }
+ pathIndex = 0;
+ return true;
+}
+
diff --git a/BranchTrace-x64plugin-wtl/ThreadTraceCore.h b/BranchTrace-x64plugin-wtl/ThreadTraceCore.h
new file mode 100644
index 0000000..a6e611d
--- /dev/null
+++ b/BranchTrace-x64plugin-wtl/ThreadTraceCore.h
@@ -0,0 +1,103 @@
+#pragma once
+#include
+#include "..\BranchTracerSys\ioctls.h"
+#include
+#include "pluginsdk\_scriptapi_flag.h"
+//#include "LDasm/LDasm.h"
+
+#include "LDasm/LDasm.h"
+
+typedef struct _BTS_RECORD64
+{
+ ULONG64 from; // ¼Ç¼·ÖÖ§µÄÔ´µØÖ·
+ ULONG64 to; // ¼Ç¼·ÖÖ§µÄÄ¿±êµØÖ·
+ union
+ {
+ ULONG64 branchPredicted;
+ ULONG64 branchType;
+ };
+}BTS_RECORD64, * PBTS_RECORD64;
+
+
+
+enum BRANCH_TYPE
+{
+ BRANCH_TYPE_UNKOWN,
+ BRANCH_TYPE_RET,
+ BRANCH_TYPE_JCC,
+ BRANCH_TYPE_CALL
+};
+bool StartTrace(DWORD ThreadId);
+bool StopTrace();
+bool StopAndFetchTrace(DWORD ThreadId, ULONG64 filterStart, ULONG64 fileterEnd, DWORD Records, PBTS_RECORD64* lpRecordStart, PBTS_RECORD64* lpRecordEnd);
+
+
+
+class TraceNode {
+
+public:
+ // pRecord.from
+ ULONG_PTR from;
+ // pRecord.to
+ ULONG_PTR to;
+ DWORD branchType;
+
+ bool hasPrev;
+ bool hasNext;
+ int prevIndex; // Ìø¹ýÖмäµÄº¯Êýµ÷ÓÃ
+ int nextIndex;
+ int procStartIndex;
+ std::vector procSubIndex;
+
+
+ // pRecord.to ~ nextRecord.from
+ std::vector paths;
+
+
+};
+
+class Proc
+{
+ std::vector nodes;
+};
+
+
+class TraceCursor {
+public:
+ int nodeIndex;
+ int pathIndex;
+
+ std::vector nodes;
+ TraceNode& currentNode() {
+ return nodes[nodeIndex];
+ }
+
+ ULONG_PTR currentAddr() {
+ return nodes[nodeIndex].paths[pathIndex];
+ }
+ DWORD branchType() {
+ return nodes[nodeIndex].branchType;
+ }
+ ULONG_PTR currentFrom() {
+ return nodes[nodeIndex].from;
+ }
+ ULONG_PTR currentTo() {
+ return nodes[nodeIndex].to;
+ }
+
+
+ bool isAtTo();
+ bool isAtFrom();
+
+ bool toEndInstr();
+ bool toPrevInstrInto();
+ bool toNextInstrInto();
+ bool toPrevInstr();
+ bool toNextInstr();
+ bool toProcStart();
+ bool toProcEnd();
+ bool toProcPrevNode();
+ bool toProcNextNode();
+};
+
+
diff --git a/BranchTrace-x64plugin-wtl/ThreadTraceDialog.cpp b/BranchTrace-x64plugin-wtl/ThreadTraceDialog.cpp
new file mode 100644
index 0000000..eb772af
--- /dev/null
+++ b/BranchTrace-x64plugin-wtl/ThreadTraceDialog.cpp
@@ -0,0 +1,545 @@
+#include "ThreadTraceDialog.h"
+#include "pluginsdk/bridgemain.h"
+#include "pluginsdk/_scriptapi_memory.h"
+#include "disassembler.h"
+#include "pluginsdk/_scriptapi_gui.h"
+#include "plugin_global.h"
+#include "pluginsdk/_scriptapi_misc.h"
+#include
+#include
+
+ThreadTraceDialog::~ThreadTraceDialog()
+{
+
+}
+
+BOOL ThreadTraceDialog::OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
+{
+ DoDataExchange(FALSE);
+ return TRUE;
+}
+
+
+void ThreadTraceDialog::OnCloseDialog()
+{
+ ShowWindow(SW_HIDE);
+ ResetAll();
+}
+
+LRESULT ThreadTraceDialog::OnDropdownComboboxThread(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+ // TODO: Add your control notification handler code here
+ THREADLIST threadList;
+ DbgGetThreadList(&threadList);
+
+ m_comboThread.ResetContent();
+
+ // ±éÀúËùÓÐÏ̳߳õʼ»¯Áбí
+ for (size_t i = 0; i < threadList.count; i++)
+ {
+ THREADALLINFO* thread = &threadList.list[i];
+
+ bool isMainThread = thread->BasicInfo.ThreadNumber == 0;
+ bool isCurrentThead = i == threadList.CurrentThread;
+
+ CString str;
+ str.Format("[%d] thread-%x %s %s", i, thread->BasicInfo.ThreadId, isMainThread ? "[main]" : "", isCurrentThead ? "[current]" : "");
+ m_comboThread.InsertString(i, str);
+ m_comboThread.SetItemData(i, thread->BasicInfo.ThreadId);
+
+ if (isMainThread) {
+ m_comboThread.SetCurSel(i);
+ }
+
+ }
+ return 1;
+}
+
+LRESULT ThreadTraceDialog::OnDropdownComboboxModule(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+ HANDLE processHandle = DbgGetProcessHandle();
+ if (processHandle == NULL) {
+ return true;
+ }
+
+ HANDLE Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, DbgGetProcessId());
+ if (Snapshot == INVALID_HANDLE_VALUE)
+ {
+ return true;
+ }
+
+ CString str;
+ str = "mod.main()";
+ duint mainModule = 0;
+ Script::Misc::ParseExpression(str.GetBuffer(), &mainModule);
+
+ m_comboModule.ResetContent();
+ MODULEENTRY32 ModuleInfo = { sizeof(MODULEENTRY32) };
+ if (Module32First(Snapshot, &ModuleInfo))
+ {
+ do {
+
+ duint moduleSize = 0;
+ str.Format("mod.size(%p)", ModuleInfo.hModule);
+ Script::Misc::ParseExpression(str.GetBuffer(), &moduleSize);
+
+ duint moduleEnd = (duint)ModuleInfo.hModule + moduleSize;
+
+ bool isMainModule = mainModule == (duint)ModuleInfo.hModule;
+ duint isUserModule = false;
+ duint isSystemModule = false;
+ str.Format("mod.user(%p)", ModuleInfo.hModule);
+ Script::Misc::ParseExpression(str.GetBuffer(), &isUserModule);
+ str.Format("mod.system(%p)", ModuleInfo.hModule);
+ Script::Misc::ParseExpression(str.GetBuffer(), &isSystemModule);
+
+
+ str.Format("[%-4s][%p] %s\n",
+ isMainModule ? "main" : isUserModule ? "user" : isSystemModule ? "syst" : "",
+ ModuleInfo.hModule, ModuleInfo.szModule);
+ int index = m_comboModule.InsertString(m_comboModule.GetCount(), str);
+ m_comboModule.SetItemData(index, (ULONG_PTR)ModuleInfo.hModule);
+
+ if (isMainModule) {
+ m_comboModule.SetCurSel(index);
+ }
+
+ } while (Module32Next(Snapshot, &ModuleInfo));
+ }
+ return true;
+}
+
+LRESULT ThreadTraceDialog::OnBnClickedButtonStarttrace(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+ // ¿ªÆô¸ú×Ù
+ int cursel = m_comboThread.GetCurSel();
+ if (cursel == -1) {
+ MessageBox(TEXT("You must select a thread!"));
+ return TRUE;
+ }
+
+ cursel = m_comboModule.GetCurSel();
+ if (cursel == -1) {
+ MessageBox(TEXT("You must select a module!"));
+ return TRUE;
+ }
+
+
+#ifdef DEBUG
+
+#else
+ if (!StartTrace(m_comboThread.GetItemData(cursel))) {
+ MessageBox(TEXT("Start Trace failed!"));
+ return FALSE;
+ }
+#endif // DEBUG
+
+ m_bTracingFlag = TRUE;
+
+ // µ÷Õû½çÃæ
+ m_buttonStarttrace.EnableWindow(FALSE);
+ m_buttonReset.EnableWindow(TRUE);
+ m_comboThread.EnableWindow(FALSE);
+ m_comboModule.EnableWindow(FALSE);
+
+ return TRUE;
+}
+
+LRESULT ThreadTraceDialog::OnBnClickedButtonReset(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+ ResetAll();
+ return TRUE;
+}
+
+
+
+LRESULT ThreadTraceDialog::OnBnClickedButtonPrevInto(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+ cursor.toPrevInstrInto();
+ ULONG_PTR addr = cursor.currentAddr();
+ GuiDisasmAt(addr, addr);
+ return TRUE;
+}
+
+
+LRESULT ThreadTraceDialog::OnBnClickedButtonNextInto(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+ cursor.toNextInstrInto();
+ ULONG_PTR addr = cursor.currentAddr();
+ GuiDisasmAt(addr, addr);
+ return TRUE;
+}
+
+LRESULT ThreadTraceDialog::OnBnClickedButtonPrev(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+
+ // »ñÈ¡ÉÏÒ»ÌõÖ¸ÁîµÄµØÖ·.
+ cursor.toPrevInstr();
+ GuiDisasmAt(cursor.currentAddr(), cursor.currentAddr());
+
+ return TRUE;
+}
+
+
+LRESULT ThreadTraceDialog::OnBnClickedButtonNext(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+
+ // »ñÈ¡ÏÂÒ»ÌõÖ¸ÁîµÄµØÖ·.
+ cursor.toNextInstr();
+ GuiDisasmAt(cursor.currentAddr(), cursor.currentAddr());
+
+ return TRUE;
+}
+
+LRESULT ThreadTraceDialog::OnBnClickedButtonProcStart(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+ cursor.toProcStart();
+ GuiDisasmAt(cursor.currentAddr(), cursor.currentAddr());
+
+
+ CString str;
+ TraceNode node = cursor.currentNode();
+
+
+ for (size_t j = 0; j < node.paths.size(); j++)
+ {
+ str.Format("traceexecute %p", node.paths[j]);
+ DbgCmdExec(str.GetBuffer());
+ }
+
+ while (node.hasNext)
+ {
+ node = cursor.nodes[node.nextIndex];
+ for (size_t j = 0; j < node.paths.size(); j++)
+ {
+ str.Format("traceexecute %p", node.paths[j]);
+ DbgCmdExec(str.GetBuffer());
+ }
+ }
+
+ return TRUE;
+}
+
+LRESULT ThreadTraceDialog::OnBnClickedButtonProcEnd(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+ cursor.toProcEnd();
+ GuiDisasmAt(cursor.currentAddr(), cursor.currentAddr());
+ return TRUE;
+}
+
+LRESULT ThreadTraceDialog::OnBnClickedButtonPrevSnippet(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+ cursor.toProcPrevNode();
+ GuiDisasmAt(cursor.currentAddr(), cursor.currentAddr());
+ return TRUE;
+}
+
+LRESULT ThreadTraceDialog::OnBnClickedButtonNextSnippet(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+ cursor.toProcNextNode();
+ GuiDisasmAt(cursor.currentAddr(), cursor.currentAddr());
+ return TRUE;
+}
+
+LRESULT ThreadTraceDialog::OnBnClickedButtonToEnd(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+ cursor.toEndInstr();
+ ULONG_PTR addr = cursor.currentAddr();
+ GuiDisasmAt(addr, addr);
+
+ return TRUE;
+}
+
+void ThreadTraceDialog::OnBreakDebugPoint()
+{
+ if (m_bTracingFlag != TRUE) {
+ return;
+ }
+
+ int threadComboCursel = m_comboThread.GetCurSel();
+ if (threadComboCursel == -1) {
+ return;
+ }
+
+ int moduleComboCursel = m_comboModule.GetCurSel();
+ if (moduleComboCursel == -1) {
+ return;
+ }
+
+
+ // ×·×ÙµÄÏß³ÌID
+ DWORD_PTR traceThreadId = m_comboThread.GetItemData(threadComboCursel);
+ DWORD_PTR moduleBase = m_comboModule.GetItemData(moduleComboCursel);
+ CString temp;
+ //duint moduleSize = 0;
+ //temp.Format("mem.size(%p)", moduleBase);
+ //Script::Misc::ParseExpression(temp.GetBuffer(), &moduleSize);
+ duint moduleSize = 0;
+ temp.Format("mod.size(%p)", moduleBase);
+ Script::Misc::ParseExpression(temp.GetBuffer(), &moduleSize);
+ DWORD_PTR moduleEnd = moduleBase + moduleSize;
+
+
+
+ // »ñÈ¡±»ÖжϵÄÏß³ÌÐÅÏ¢
+ THREADLIST threadList;
+ DbgGetThreadList(&threadList);
+ DWORD breakedThread = threadList.list[threadList.CurrentThread].BasicInfo.ThreadId;
+
+ if (traceThreadId != breakedThread) {
+ return;
+ }
+
+ // Í£Ö¹¼à¿Ø
+ if (!StopAndFetchTrace(traceThreadId, moduleBase, moduleEnd, 5000, &RecordStart, &RecordEnd)) {
+ MessageBox("Fetch trace record failed!");
+ m_bTracingFlag = FALSE;
+ return;
+ }
+
+ m_bTracingFlag = FALSE;
+
+
+ // ½âÎöÖ¸Áî
+ Disassembler* disasm = PluginGlobal::GetInstance()->disassembler;
+ Instruction instrction;
+ duint readSize;
+ unsigned char instrBuffer[0x10];
+ PBTS_RECORD64 pRecord = RecordEnd - 1;
+ while (pRecord >= RecordStart)
+ {
+ Script::Memory::Read((duint)pRecord->from, instrBuffer, 0x10, &readSize);
+
+ if (!disasm->Disasm(instrBuffer, readSize, &instrction)) {
+ _plugin_logprintf("BranchTrace Error: Disasm failed! codes:");
+ for (duint i = 0; i < readSize; i++) {
+ _plugin_logprintf("%x ", instrBuffer[i]);
+ }
+ continue;
+ }
+ ZydisMnemonic mnemonic = instrction.zydisInstrction.mnemonic;
+ if (mnemonic == ZYDIS_MNEMONIC_RET) {
+ pRecord->branchType = BRANCH_TYPE_RET;
+ }
+ else if (ZYDIS_MNEMONIC_JB <= mnemonic && mnemonic <= ZYDIS_MNEMONIC_JZ) {
+ pRecord->branchType = BRANCH_TYPE_JCC;
+ }
+ else if (mnemonic == ZYDIS_MNEMONIC_CALL) {
+ pRecord->branchType = BRANCH_TYPE_CALL;
+ }
+ else {
+ // UNKOWN Instrction;
+ pRecord->branchType = BRANCH_TYPE_UNKOWN;
+ _plugin_logprintf("UNKOWN at : %p mnemonic:%d \n", pRecord->from, instrction.zydisInstrction.mnemonic);
+ }
+
+ pRecord--;
+ }
+
+
+
+ // ´æ´¢Êý¾Ý
+ cursor.nodes.clear();
+ int instrCount = 0;
+
+ std::map PrcoToMap;;
+ std::stack ProcStak;
+
+ CString str;
+ pRecord = RecordStart;
+
+ while (pRecord < RecordEnd)
+ {
+ int currentNodeIndex = cursor.nodes.size();
+ // ¼ÓÈëÁбí
+ cursor.nodes.emplace_back();
+ TraceNode& node = cursor.nodes.back();
+
+ node.from = pRecord->from;
+ node.to = pRecord->to;
+ node.branchType = pRecord->branchType;
+
+ node.paths.push_back(pRecord->to);
+ instrCount++;
+
+ // Ìî³ä´úÂë¿é
+ PBTS_RECORD64 pNextRecord = pRecord + 1;
+
+ str.Format("dis.next(%p)", pRecord->to);
+ duint nextInstr = 0;
+ Script::Misc::ParseExpression(str.GetBuffer(), &nextInstr);
+
+ if (pNextRecord < RecordEnd)
+ {
+ // ±ÜÃâÔàÊý¾Ý,´óÓÚ500×ֽڵĴúÂë¿éÖ±½ÓÌø¹ý
+ ULONG64 offset = pNextRecord->from - nextInstr;
+ while (nextInstr != 0 && nextInstr <= pNextRecord->from && offset < 500)
+ {
+ node.paths.push_back(nextInstr);
+ instrCount++;
+
+ str.Format("dis.next(%p)", nextInstr);
+ nextInstr = 0;
+ Script::Misc::ParseExpression(str.GetBuffer(), &nextInstr);
+ }
+
+ }
+
+ // 񈬀procStartIndex procSubNodeIndex
+ switch (node.branchType)
+ {
+ case BRANCH_TYPE_CALL:
+ ProcStak.push(currentNodeIndex);
+ node.procStartIndex = currentNodeIndex;
+ cursor.nodes[currentNodeIndex].procSubIndex.push_back(currentNodeIndex);
+ break;
+
+ case BRANCH_TYPE_RET:
+
+ if (!ProcStak.empty()) {
+ ProcStak.pop();
+ }
+
+ if (!ProcStak.empty()) {
+ node.procStartIndex = ProcStak.top();
+ cursor.nodes[ProcStak.top()].procSubIndex.push_back(currentNodeIndex);
+ }
+ else {
+ node.procStartIndex = currentNodeIndex;
+ cursor.nodes[currentNodeIndex].procSubIndex.push_back(currentNodeIndex);
+ }
+ break;
+
+ case BRANCH_TYPE_JCC:
+ if (!ProcStak.empty()) {
+ node.procStartIndex = ProcStak.top();
+ cursor.nodes[ProcStak.top()].procSubIndex.push_back(currentNodeIndex);
+
+ }
+ else {
+ node.procStartIndex = currentNodeIndex;
+ cursor.nodes[currentNodeIndex].procSubIndex.push_back(currentNodeIndex);
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ // ±ê¼Ç PrcoÁ´ 1~2~3~4
+ if (node.branchType == BRANCH_TYPE_CALL) {
+
+ duint nextInstr = 0;
+ str.Format("dis.next(%p)", pRecord->from);
+ Script::Misc::ParseExpression(str.GetBuffer(), &nextInstr);
+ if (nextInstr != 0) {
+ PrcoToMap[nextInstr] = currentNodeIndex - 1;
+ }
+
+ }
+ else if (node.branchType == BRANCH_TYPE_RET)
+ {
+ if (PrcoToMap.count(node.to) > 0) {
+ auto preIndex = PrcoToMap[node.to];
+ auto curIndex = currentNodeIndex;
+
+ cursor.nodes[preIndex].nextIndex = curIndex;
+ cursor.nodes[preIndex].hasNext = true;
+ cursor.nodes[curIndex].prevIndex = preIndex;
+ cursor.nodes[curIndex].hasPrev = true;
+
+ PrcoToMap.erase(node.to);
+ }
+ }
+ else if (node.branchType == BRANCH_TYPE_JCC)
+ {
+ if (currentNodeIndex > 0) {
+ auto preIndex = currentNodeIndex - 1;
+ auto curIndex = currentNodeIndex;
+ cursor.nodes[preIndex].nextIndex = curIndex;
+ cursor.nodes[preIndex].hasNext = true;
+ cursor.nodes[curIndex].prevIndex = preIndex;
+ cursor.nodes[curIndex].hasPrev = true;
+ }
+ }
+ pRecord++;
+ }
+
+
+
+
+
+ // ÉèÖÃÆðʼλÖÃ
+ cursor.toEndInstr();
+ GuiDisasmAt(cursor.currentAddr(), cursor.currentAddr());
+
+ // ÉèÖÿؼþ״̬
+ m_comboThread.EnableWindow(FALSE);
+ m_buttonPrevInto.EnableWindow(TRUE);
+ m_buttonNextInto.EnableWindow(TRUE);
+ m_buttonProcStart.EnableWindow(TRUE);
+ m_buttonProcEnd.EnableWindow(TRUE);
+ m_buttonPrevSnippet.EnableWindow(TRUE);
+ m_buttonNextSnippet.EnableWindow(TRUE);
+ m_buttonPrev.EnableWindow(TRUE);
+ m_buttonNext.EnableWindow(TRUE);
+ m_buttonToEnd.EnableWindow(TRUE);
+
+
+ CString note;
+ int count = RecordEnd - RecordStart;
+ note.Format(TEXT("Fetched Branch Records!\r\n Branch count: %d\r\nInstrction count: %d"), count, instrCount);
+ MessageBox(note, TEXT("SUCCESS"));
+
+
+
+ // ÊÍ·ÅÄÚ´æ
+ if (RecordStart) {
+ VirtualFree((PVOID)RecordStart, 0, MEM_RELEASE);
+ RecordStart = NULL;
+ RecordEnd = NULL;
+ }
+
+}
+
+void ThreadTraceDialog::ResetAll()
+{
+ // Í£Ö¹¼à¿Ø
+ StopTrace();
+ m_bTracingFlag = FALSE;
+
+ // ÖØÖÿؼþ
+ m_buttonStarttrace.EnableWindow(TRUE);
+ m_buttonReset.EnableWindow(FALSE);
+ m_buttonPrevInto.EnableWindow(FALSE);
+ m_buttonNextInto.EnableWindow(FALSE);
+ m_buttonProcStart.EnableWindow(FALSE);
+ m_buttonProcEnd.EnableWindow(FALSE);
+ m_buttonPrevSnippet.EnableWindow(FALSE);
+ m_buttonNextSnippet.EnableWindow(FALSE);
+ m_buttonPrev.EnableWindow(FALSE);
+ m_buttonNext.EnableWindow(FALSE);
+ m_buttonToEnd.EnableWindow(FALSE);
+
+ m_comboThread.EnableWindow(TRUE);
+ m_comboThread.SetCurSel(-1);
+ m_comboModule.EnableWindow(TRUE);
+ m_comboModule.SetCurSel(-1);
+
+
+
+}
+
+void ThreadTraceDialog::HighlightTrace()
+{
+ //PBTS_RECORD64 pRecord = RecordCursor;
+ //CString str;
+ //str.Format("traceexecute %p", pRecord->to);
+ //DbgCmdExec(str.GetBuffer());
+ //str.Format("traceexecute %p", pRecord->from);
+ //DbgCmdExec(str.GetBuffer());
+
+ return;
+}
+
+
diff --git a/BranchTrace-x64plugin-wtl/ThreadTraceDialog.h b/BranchTrace-x64plugin-wtl/ThreadTraceDialog.h
new file mode 100644
index 0000000..5af39b5
--- /dev/null
+++ b/BranchTrace-x64plugin-wtl/ThreadTraceDialog.h
@@ -0,0 +1,114 @@
+#pragma once
+#include "stdafx.h"
+#include "ThreadTraceCore.h"
+
+
+class ThreadTraceDialog : public CDialogImpl, public CWinDataExchange
+{
+
+protected:
+
+ // ¿Ø¼þ
+ CComboBoxImpl m_comboThread;
+ CComboBoxImpl m_comboModule;
+ CButtonImpl m_buttonStarttrace;
+ CButtonImpl m_buttonReset;
+ CButtonImpl m_buttonPrevInto;
+ CButtonImpl m_buttonNextInto;
+ CButtonImpl m_buttonProcStart;
+ CButtonImpl m_buttonProcEnd;
+ CButtonImpl m_buttonPrevSnippet;
+ CButtonImpl m_buttonNextSnippet;
+ CButtonImpl m_buttonPrev;
+ CButtonImpl m_buttonNext;
+ CButtonImpl m_buttonToEnd;
+
+
+ PBTS_RECORD64 RecordStart = NULL;
+ PBTS_RECORD64 RecordEnd = NULL;
+ PBTS_RECORD64 RecordCursor = NULL;
+ BOOL ToFromFlag = TRUE;
+ TraceCursor cursor;
+
+
+#define AT_TO TRUE
+#define AT_FROM FALSE
+ BOOL m_bTracingFlag; // AT_TO | AT_FROM
+
+
+public:
+ ThreadTraceDialog() : RecordStart(NULL), RecordEnd(NULL), m_bTracingFlag(FALSE) {};
+ ~ThreadTraceDialog();
+
+
+ // msg handler
+ BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam);
+ void OnCloseDialog();
+
+ // command hander
+ LRESULT OnDropdownComboboxThread(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+ LRESULT OnDropdownComboboxModule(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+ LRESULT OnBnClickedButtonStarttrace(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+ LRESULT OnBnClickedButtonReset(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+ LRESULT OnBnClickedButtonPrevInto(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+ LRESULT OnBnClickedButtonNextInto(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+ LRESULT OnBnClickedButtonProcStart(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+ LRESULT OnBnClickedButtonProcEnd(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+ LRESULT OnBnClickedButtonPrevSnippet(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+ LRESULT OnBnClickedButtonNextSnippet(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+ LRESULT OnBnClickedButtonPrev(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+ LRESULT OnBnClickedButtonNext(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+ LRESULT OnBnClickedButtonToEnd(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+
+ void OnBreakDebugPoint();
+ void ResetAll();
+ void HighlightTrace();
+
+
+public:
+ enum { IDD = IDD_DIALOG_THREAD_TRACE };
+
+ BEGIN_MSG_MAP(ThreadTraceDialog)
+ // commands
+ MSG_WM_INITDIALOG(OnInitDialog)
+ MSG_WM_CLOSE(OnCloseDialog)
+
+ // combo-box
+ COMMAND_HANDLER(IDC_COMBO_THREAD, CBN_DROPDOWN, OnDropdownComboboxThread)
+ COMMAND_HANDLER(IDC_COMBO_MODULE, CBN_DROPDOWN, OnDropdownComboboxModule)
+
+ // buttons
+ COMMAND_ID_HANDLER(IDC_BUTTON_STARTTRACE, OnBnClickedButtonStarttrace)
+ COMMAND_ID_HANDLER(IDC_BUTTON_RESET, OnBnClickedButtonReset)
+ COMMAND_ID_HANDLER(IDC_BUTTON_PREVINTO, OnBnClickedButtonPrevInto)
+ COMMAND_ID_HANDLER(IDC_BUTTON_NEXTINTO, OnBnClickedButtonNextInto)
+ COMMAND_ID_HANDLER(IDC_BUTTON_PROCSTART, OnBnClickedButtonProcStart)
+ COMMAND_ID_HANDLER(IDC_BUTTON_PROCEND, OnBnClickedButtonProcEnd)
+ COMMAND_ID_HANDLER(IDC_BUTTON_PREVSNIPPET, OnBnClickedButtonPrevSnippet)
+ COMMAND_ID_HANDLER(IDC_BUTTON_NEXTSNIPPET, OnBnClickedButtonNextSnippet)
+ COMMAND_ID_HANDLER(IDC_BUTTON_PREV, OnBnClickedButtonPrev)
+ COMMAND_ID_HANDLER(IDC_BUTTON_NEXT, OnBnClickedButtonNext)
+ COMMAND_ID_HANDLER(IDC_BUTTON_TOEND, OnBnClickedButtonToEnd)
+
+ END_MSG_MAP()
+
+
+ BEGIN_DDX_MAP(ThreadTraceDialog)
+ // controls
+ DDX_CONTROL(IDC_COMBO_THREAD, m_comboThread)
+ DDX_CONTROL(IDC_COMBO_MODULE, m_comboModule)
+ DDX_CONTROL(IDC_BUTTON_STARTTRACE, m_buttonStarttrace)
+ DDX_CONTROL(IDC_BUTTON_RESET, m_buttonReset)
+ DDX_CONTROL(IDC_BUTTON_PREVINTO, m_buttonPrevInto)
+ DDX_CONTROL(IDC_BUTTON_NEXTINTO, m_buttonNextInto)
+ DDX_CONTROL(IDC_BUTTON_PROCSTART, m_buttonProcStart)
+ DDX_CONTROL(IDC_BUTTON_PROCEND, m_buttonProcEnd)
+ DDX_CONTROL(IDC_BUTTON_PREVSNIPPET, m_buttonPrevSnippet)
+ DDX_CONTROL(IDC_BUTTON_NEXTSNIPPET, m_buttonNextSnippet)
+
+ DDX_CONTROL(IDC_BUTTON_PREV, m_buttonPrev)
+ DDX_CONTROL(IDC_BUTTON_NEXT, m_buttonNext)
+ DDX_CONTROL(IDC_BUTTON_TOEND, m_buttonToEnd)
+ END_DDX_MAP()
+
+};
\ No newline at end of file
diff --git a/BranchTrace-x64plugin-wtl/disassembler.cpp b/BranchTrace-x64plugin-wtl/disassembler.cpp
new file mode 100644
index 0000000..a606164
--- /dev/null
+++ b/BranchTrace-x64plugin-wtl/disassembler.cpp
@@ -0,0 +1,321 @@
+#include "disassembler.h"
+#include
+#include
+
+
+Disassembler::Disassembler()
+{
+#ifdef _WIN64
+ ZydisDecoderInit(&zydisDecoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64);
+#else
+ ZydisDecoderInit(&zydisDecoder, ZYDIS_MACHINE_MODE_LONG_COMPAT_32, ZYDIS_ADDRESS_WIDTH_32);
+#endif // _WIN64
+}
+
+
+bool Disassembler::Disasm(unsigned char* code, size_t codesize, Instruction* instruction)
+{
+ return ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(&zydisDecoder, code, codesize, &(instruction->zydisInstrction)));
+}
+
+const char* Disassembler::FormatZydisRegister(ZydisRegister reg)
+{
+ switch (reg)
+ {
+ case ZYDIS_REGISTER_NONE: return "";
+ case ZYDIS_REGISTER_AL: return "al";
+ case ZYDIS_REGISTER_CL: return "cl";
+ case ZYDIS_REGISTER_DL: return "dl";
+ case ZYDIS_REGISTER_BL: return "bl";
+ case ZYDIS_REGISTER_AH: return "ah";
+ case ZYDIS_REGISTER_CH: return "ch";
+ case ZYDIS_REGISTER_DH: return "dh";
+ case ZYDIS_REGISTER_BH: return "bh";
+ case ZYDIS_REGISTER_SPL: return "spl";
+ case ZYDIS_REGISTER_BPL: return "bpl";
+ case ZYDIS_REGISTER_SIL: return "sil";
+ case ZYDIS_REGISTER_DIL: return "dil";
+ case ZYDIS_REGISTER_R8B: return "r8b";
+ case ZYDIS_REGISTER_R9B: return "r9b";
+ case ZYDIS_REGISTER_R10B: return "r10b";
+ case ZYDIS_REGISTER_R11B: return "r11b";
+ case ZYDIS_REGISTER_R12B: return "r12b";
+ case ZYDIS_REGISTER_R13B: return "r13b";
+ case ZYDIS_REGISTER_R14B: return "r14b";
+ case ZYDIS_REGISTER_R15B: return "r15b";
+ case ZYDIS_REGISTER_AX: return "ax";
+ case ZYDIS_REGISTER_CX: return "cx";
+ case ZYDIS_REGISTER_DX: return "dx";
+ case ZYDIS_REGISTER_BX: return "bx";
+ case ZYDIS_REGISTER_SP: return "sp";
+ case ZYDIS_REGISTER_BP: return "bp";
+ case ZYDIS_REGISTER_SI: return "si";
+ case ZYDIS_REGISTER_DI: return "di";
+ case ZYDIS_REGISTER_R8W: return "r8w";
+ case ZYDIS_REGISTER_R9W: return "r9w";
+ case ZYDIS_REGISTER_R10W: return "r10w";
+ case ZYDIS_REGISTER_R11W: return "r11w";
+ case ZYDIS_REGISTER_R12W: return "r12w";
+ case ZYDIS_REGISTER_R13W: return "r13w";
+ case ZYDIS_REGISTER_R14W: return "r14w";
+ case ZYDIS_REGISTER_R15W: return "r15w";
+ case ZYDIS_REGISTER_EAX: return "eax";
+ case ZYDIS_REGISTER_ECX: return "ecx";
+ case ZYDIS_REGISTER_EDX: return "edx";
+ case ZYDIS_REGISTER_EBX: return "ebx";
+ case ZYDIS_REGISTER_ESP: return "esp";
+ case ZYDIS_REGISTER_EBP: return "ebp";
+ case ZYDIS_REGISTER_ESI: return "esi";
+ case ZYDIS_REGISTER_EDI: return "edi";
+ case ZYDIS_REGISTER_R8D: return "r8d";
+ case ZYDIS_REGISTER_R9D: return "r9d";
+ case ZYDIS_REGISTER_R10D: return "r10d";
+ case ZYDIS_REGISTER_R11D: return "r11d";
+ case ZYDIS_REGISTER_R12D: return "r12d";
+ case ZYDIS_REGISTER_R13D: return "r13d";
+ case ZYDIS_REGISTER_R14D: return "r14d";
+ case ZYDIS_REGISTER_R15D: return "r15d";
+ case ZYDIS_REGISTER_RAX: return "rax";
+ case ZYDIS_REGISTER_RCX: return "rcx";
+ case ZYDIS_REGISTER_RDX: return "rdx";
+ case ZYDIS_REGISTER_RBX: return "rbx";
+ case ZYDIS_REGISTER_RSP: return "rsp";
+ case ZYDIS_REGISTER_RBP: return "rbp";
+ case ZYDIS_REGISTER_RSI: return "rsi";
+ case ZYDIS_REGISTER_RDI: return "rdi";
+ case ZYDIS_REGISTER_R8: return "r8";
+ case ZYDIS_REGISTER_R9: return "r9";
+ case ZYDIS_REGISTER_R10: return "r10";
+ case ZYDIS_REGISTER_R11: return "r11";
+ case ZYDIS_REGISTER_R12: return "r12";
+ case ZYDIS_REGISTER_R13: return "r13";
+ case ZYDIS_REGISTER_R14: return "r14";
+ case ZYDIS_REGISTER_R15: return "r15";
+ case ZYDIS_REGISTER_ST0: return "st0";
+ case ZYDIS_REGISTER_ST1: return "st1";
+ case ZYDIS_REGISTER_ST2: return "st2";
+ case ZYDIS_REGISTER_ST3: return "st3";
+ case ZYDIS_REGISTER_ST4: return "st4";
+ case ZYDIS_REGISTER_ST5: return "st5";
+ case ZYDIS_REGISTER_ST6: return "st6";
+ case ZYDIS_REGISTER_ST7: return "st7";
+ case ZYDIS_REGISTER_X87CONTROL: return "x87control";
+ case ZYDIS_REGISTER_X87STATUS: return "x87status";
+ case ZYDIS_REGISTER_X87TAG: return "x87tag";
+ case ZYDIS_REGISTER_MM0: return "mm0";
+ case ZYDIS_REGISTER_MM1: return "mm1";
+ case ZYDIS_REGISTER_MM2: return "mm2";
+ case ZYDIS_REGISTER_MM3: return "mm3";
+ case ZYDIS_REGISTER_MM4: return "mm4";
+ case ZYDIS_REGISTER_MM5: return "mm5";
+ case ZYDIS_REGISTER_MM6: return "mm6";
+ case ZYDIS_REGISTER_MM7: return "mm7";
+ case ZYDIS_REGISTER_XMM0: return "xmm0";
+ case ZYDIS_REGISTER_XMM1: return "xmm1";
+ case ZYDIS_REGISTER_XMM2: return "xmm2";
+ case ZYDIS_REGISTER_XMM3: return "xmm3";
+ case ZYDIS_REGISTER_XMM4: return "xmm4";
+ case ZYDIS_REGISTER_XMM5: return "xmm5";
+ case ZYDIS_REGISTER_XMM6: return "xmm6";
+ case ZYDIS_REGISTER_XMM7: return "xmm7";
+ case ZYDIS_REGISTER_XMM8: return "xmm8";
+ case ZYDIS_REGISTER_XMM9: return "xmm9";
+ case ZYDIS_REGISTER_XMM10: return "xmm10";
+ case ZYDIS_REGISTER_XMM11: return "xmm11";
+ case ZYDIS_REGISTER_XMM12: return "xmm12";
+ case ZYDIS_REGISTER_XMM13: return "xmm13";
+ case ZYDIS_REGISTER_XMM14: return "xmm14";
+ case ZYDIS_REGISTER_XMM15: return "xmm15";
+ case ZYDIS_REGISTER_XMM16: return "xmm16";
+ case ZYDIS_REGISTER_XMM17: return "xmm17";
+ case ZYDIS_REGISTER_XMM18: return "xmm18";
+ case ZYDIS_REGISTER_XMM19: return "xmm19";
+ case ZYDIS_REGISTER_XMM20: return "xmm20";
+ case ZYDIS_REGISTER_XMM21: return "xmm21";
+ case ZYDIS_REGISTER_XMM22: return "xmm22";
+ case ZYDIS_REGISTER_XMM23: return "xmm23";
+ case ZYDIS_REGISTER_XMM24: return "xmm24";
+ case ZYDIS_REGISTER_XMM25: return "xmm25";
+ case ZYDIS_REGISTER_XMM26: return "xmm26";
+ case ZYDIS_REGISTER_XMM27: return "xmm27";
+ case ZYDIS_REGISTER_XMM28: return "xmm28";
+ case ZYDIS_REGISTER_XMM29: return "xmm29";
+ case ZYDIS_REGISTER_XMM30: return "xmm30";
+ case ZYDIS_REGISTER_XMM31: return "xmm31";
+ case ZYDIS_REGISTER_YMM0: return "ymm0";
+ case ZYDIS_REGISTER_YMM1: return "ymm1";
+ case ZYDIS_REGISTER_YMM2: return "ymm2";
+ case ZYDIS_REGISTER_YMM3: return "ymm3";
+ case ZYDIS_REGISTER_YMM4: return "ymm4";
+ case ZYDIS_REGISTER_YMM5: return "ymm5";
+ case ZYDIS_REGISTER_YMM6: return "ymm6";
+ case ZYDIS_REGISTER_YMM7: return "ymm7";
+ case ZYDIS_REGISTER_YMM8: return "ymm8";
+ case ZYDIS_REGISTER_YMM9: return "ymm9";
+ case ZYDIS_REGISTER_YMM10: return "ymm10";
+ case ZYDIS_REGISTER_YMM11: return "ymm11";
+ case ZYDIS_REGISTER_YMM12: return "ymm12";
+ case ZYDIS_REGISTER_YMM13: return "ymm13";
+ case ZYDIS_REGISTER_YMM14: return "ymm14";
+ case ZYDIS_REGISTER_YMM15: return "ymm15";
+ case ZYDIS_REGISTER_YMM16: return "ymm16";
+ case ZYDIS_REGISTER_YMM17: return "ymm17";
+ case ZYDIS_REGISTER_YMM18: return "ymm18";
+ case ZYDIS_REGISTER_YMM19: return "ymm19";
+ case ZYDIS_REGISTER_YMM20: return "ymm20";
+ case ZYDIS_REGISTER_YMM21: return "ymm21";
+ case ZYDIS_REGISTER_YMM22: return "ymm22";
+ case ZYDIS_REGISTER_YMM23: return "ymm23";
+ case ZYDIS_REGISTER_YMM24: return "ymm24";
+ case ZYDIS_REGISTER_YMM25: return "ymm25";
+ case ZYDIS_REGISTER_YMM26: return "ymm26";
+ case ZYDIS_REGISTER_YMM27: return "ymm27";
+ case ZYDIS_REGISTER_YMM28: return "ymm28";
+ case ZYDIS_REGISTER_YMM29: return "ymm29";
+ case ZYDIS_REGISTER_YMM30: return "ymm30";
+ case ZYDIS_REGISTER_YMM31: return "ymm31";
+ case ZYDIS_REGISTER_ZMM0: return "zmm0";
+ case ZYDIS_REGISTER_ZMM1: return "zmm1";
+ case ZYDIS_REGISTER_ZMM2: return "zmm2";
+ case ZYDIS_REGISTER_ZMM3: return "zmm3";
+ case ZYDIS_REGISTER_ZMM4: return "zmm4";
+ case ZYDIS_REGISTER_ZMM5: return "zmm5";
+ case ZYDIS_REGISTER_ZMM6: return "zmm6";
+ case ZYDIS_REGISTER_ZMM7: return "zmm7";
+ case ZYDIS_REGISTER_ZMM8: return "zmm8";
+ case ZYDIS_REGISTER_ZMM9: return "zmm9";
+ case ZYDIS_REGISTER_ZMM10: return "zmm10";
+ case ZYDIS_REGISTER_ZMM11: return "zmm11";
+ case ZYDIS_REGISTER_ZMM12: return "zmm12";
+ case ZYDIS_REGISTER_ZMM13: return "zmm13";
+ case ZYDIS_REGISTER_ZMM14: return "zmm14";
+ case ZYDIS_REGISTER_ZMM15: return "zmm15";
+ case ZYDIS_REGISTER_ZMM16: return "zmm16";
+ case ZYDIS_REGISTER_ZMM17: return "zmm17";
+ case ZYDIS_REGISTER_ZMM18: return "zmm18";
+ case ZYDIS_REGISTER_ZMM19: return "zmm19";
+ case ZYDIS_REGISTER_ZMM20: return "zmm20";
+ case ZYDIS_REGISTER_ZMM21: return "zmm21";
+ case ZYDIS_REGISTER_ZMM22: return "zmm22";
+ case ZYDIS_REGISTER_ZMM23: return "zmm23";
+ case ZYDIS_REGISTER_ZMM24: return "zmm24";
+ case ZYDIS_REGISTER_ZMM25: return "zmm25";
+ case ZYDIS_REGISTER_ZMM26: return "zmm26";
+ case ZYDIS_REGISTER_ZMM27: return "zmm27";
+ case ZYDIS_REGISTER_ZMM28: return "zmm28";
+ case ZYDIS_REGISTER_ZMM29: return "zmm29";
+ case ZYDIS_REGISTER_ZMM30: return "zmm30";
+ case ZYDIS_REGISTER_ZMM31: return "zmm31";
+ case ZYDIS_REGISTER_FLAGS: return "flags";
+ case ZYDIS_REGISTER_EFLAGS: return "eflags";
+ case ZYDIS_REGISTER_RFLAGS: return "rflags";
+ case ZYDIS_REGISTER_IP: return "ip";
+ case ZYDIS_REGISTER_EIP: return "eip";
+ case ZYDIS_REGISTER_RIP: return "rip";
+ case ZYDIS_REGISTER_ES: return "es";
+ case ZYDIS_REGISTER_CS: return "cs";
+ case ZYDIS_REGISTER_SS: return "ss";
+ case ZYDIS_REGISTER_DS: return "ds";
+ case ZYDIS_REGISTER_FS: return "fs";
+ case ZYDIS_REGISTER_GS: return "gs";
+ case ZYDIS_REGISTER_GDTR: return "gdtr";
+ case ZYDIS_REGISTER_LDTR: return "ldtr";
+ case ZYDIS_REGISTER_IDTR: return "idtr";
+ case ZYDIS_REGISTER_TR: return "tr";
+ case ZYDIS_REGISTER_TR0: return "tr0";
+ case ZYDIS_REGISTER_TR1: return "tr1";
+ case ZYDIS_REGISTER_TR2: return "tr2";
+ case ZYDIS_REGISTER_TR3: return "tr3";
+ case ZYDIS_REGISTER_TR4: return "tr4";
+ case ZYDIS_REGISTER_TR5: return "tr5";
+ case ZYDIS_REGISTER_TR6: return "tr6";
+ case ZYDIS_REGISTER_TR7: return "tr7";
+ case ZYDIS_REGISTER_CR0: return "cr0";
+ case ZYDIS_REGISTER_CR1: return "cr1";
+ case ZYDIS_REGISTER_CR2: return "cr2";
+ case ZYDIS_REGISTER_CR3: return "cr3";
+ case ZYDIS_REGISTER_CR4: return "cr4";
+ case ZYDIS_REGISTER_CR5: return "cr5";
+ case ZYDIS_REGISTER_CR6: return "cr6";
+ case ZYDIS_REGISTER_CR7: return "cr7";
+ case ZYDIS_REGISTER_CR8: return "cr8";
+ case ZYDIS_REGISTER_CR9: return "cr9";
+ case ZYDIS_REGISTER_CR10: return "cr10";
+ case ZYDIS_REGISTER_CR11: return "cr11";
+ case ZYDIS_REGISTER_CR12: return "cr12";
+ case ZYDIS_REGISTER_CR13: return "cr13";
+ case ZYDIS_REGISTER_CR14: return "cr14";
+ case ZYDIS_REGISTER_CR15: return "cr15";
+ case ZYDIS_REGISTER_DR0: return "dr0";
+ case ZYDIS_REGISTER_DR1: return "dr1";
+ case ZYDIS_REGISTER_DR2: return "dr2";
+ case ZYDIS_REGISTER_DR3: return "dr3";
+ case ZYDIS_REGISTER_DR4: return "dr4";
+ case ZYDIS_REGISTER_DR5: return "dr5";
+ case ZYDIS_REGISTER_DR6: return "dr6";
+ case ZYDIS_REGISTER_DR7: return "dr7";
+ case ZYDIS_REGISTER_DR8: return "dr8";
+ case ZYDIS_REGISTER_DR9: return "dr9";
+ case ZYDIS_REGISTER_DR10: return "dr10";
+ case ZYDIS_REGISTER_DR11: return "dr11";
+ case ZYDIS_REGISTER_DR12: return "dr12";
+ case ZYDIS_REGISTER_DR13: return "dr13";
+ case ZYDIS_REGISTER_DR14: return "dr14";
+ case ZYDIS_REGISTER_DR15: return "dr15";
+ case ZYDIS_REGISTER_K0: return "k0";
+ case ZYDIS_REGISTER_K1: return "k1";
+ case ZYDIS_REGISTER_K2: return "k2";
+ case ZYDIS_REGISTER_K3: return "k3";
+ case ZYDIS_REGISTER_K4: return "k4";
+ case ZYDIS_REGISTER_K5: return "k5";
+ case ZYDIS_REGISTER_K6: return "k6";
+ case ZYDIS_REGISTER_K7: return "k7";
+ case ZYDIS_REGISTER_BND0: return "bnd0";
+ case ZYDIS_REGISTER_BND1: return "bnd1";
+ case ZYDIS_REGISTER_BND2: return "bnd2";
+ case ZYDIS_REGISTER_BND3: return "bnd3";
+ case ZYDIS_REGISTER_BNDCFG: return "bndcfg";
+ case ZYDIS_REGISTER_BNDSTATUS: return "bndstatus";
+ case ZYDIS_REGISTER_MXCSR: return "mxcsr";
+ case ZYDIS_REGISTER_PKRU: return "pkru";
+ case ZYDIS_REGISTER_XCR0: return "xcr0";
+ }
+ return "";
+}
+
+
+void Disassembler::loadPage(void* buffer, size_t pageAddr)
+{
+ if (m_pageInstrAddrMap.count(pageAddr) != 0) {
+ return;
+ }
+
+
+ std::vector addrList;
+ std::map indexMap;
+
+ Instruction instr;
+ int index = 0;
+ size_t position = 0;
+ while (position < 0x1000)
+ {
+ if (Disasm((unsigned char*)buffer + position, 0x1000 - position, &instr) == false) {
+ break;
+ }
+ instr.zydisInstrction.length;
+
+ addrList.push_back(pageAddr + position);
+ indexMap.insert(std::make_pair(pageAddr + position, index));
+
+ index++;
+ position += instr.zydisInstrction.length;
+ }
+
+ m_pageInstrAddrMap.insert(std::make_pair(pageAddr, addrList));
+ m_pageInstrAddrIndexMap.insert(std::make_pair(pageAddr, indexMap));
+}
+
+void Disassembler::Reset()
+{
+
+}
diff --git a/BranchTrace-x64plugin-wtl/disassembler.h b/BranchTrace-x64plugin-wtl/disassembler.h
new file mode 100644
index 0000000..044a2ad
--- /dev/null
+++ b/BranchTrace-x64plugin-wtl/disassembler.h
@@ -0,0 +1,30 @@
+#pragma once
+#pragma warning(disable 26812)
+#include
+#include