Merge branch 'master' of https://github.com/x64dbg/x64dbg
Conflicts: x64_dbg_dbg/functionanalysis.cpp x64_dbg_dbg/x64_dbg_dbg.vcxproj x64_dbg_dbg/x64_dbg_dbg.vcxproj.filters
This commit is contained in:
		
						commit
						ab3ecaf054
					
				|  | @ -1120,6 +1120,26 @@ BRIDGE_IMPEXP void GuiShowCpu() | ||||||
|     _gui_sendmessage(GUI_SHOW_CPU, 0, 0); |     _gui_sendmessage(GUI_SHOW_CPU, 0, 0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | BRIDGE_IMPEXP void GuiAddQWidgetTab(void* qWidget) | ||||||
|  | { | ||||||
|  |     _gui_sendmessage(GUI_ADD_QWIDGET_TAB, qWidget, nullptr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BRIDGE_IMPEXP void GuiShowQWidgetTab(void* qWidget) | ||||||
|  | { | ||||||
|  |     _gui_sendmessage(GUI_SHOW_QWIDGET_TAB, qWidget, nullptr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BRIDGE_IMPEXP void GuiCloseQWidgetTab(void* qWidget) | ||||||
|  | { | ||||||
|  |     _gui_sendmessage(GUI_CLOSE_QWIDGET_TAB, qWidget, nullptr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BRIDGE_IMPEXP void GuiExecuteOnGuiThread(GUICALLBACK cbGuiThread) | ||||||
|  | { | ||||||
|  |     _gui_sendmessage(GUI_EXECUTE_ON_GUI_THREAD, cbGuiThread, nullptr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) | ||||||
| { | { | ||||||
|     hInst = hinstDLL; |     hInst = hinstDLL; | ||||||
|  |  | ||||||
|  | @ -761,9 +761,16 @@ typedef enum | ||||||
|     GUI_LOAD_SOURCE_FILE,           // param1=const char* path,     param2=line
 |     GUI_LOAD_SOURCE_FILE,           // param1=const char* path,     param2=line
 | ||||||
|     GUI_MENU_SET_ICON,              // param1=int hMenu,            param2=ICONINFO*
 |     GUI_MENU_SET_ICON,              // param1=int hMenu,            param2=ICONINFO*
 | ||||||
|     GUI_MENU_SET_ENTRY_ICON,        // param1=int hEntry,           param2=ICONINFO*
 |     GUI_MENU_SET_ENTRY_ICON,        // param1=int hEntry,           param2=ICONINFO*
 | ||||||
|     GUI_SHOW_CPU                    // param1=unused,               param2=unused
 |     GUI_SHOW_CPU,                   // param1=unused,               param2=unused
 | ||||||
|  |     GUI_ADD_QWIDGET_TAB,            // param1=QWidget*,             param2=unused
 | ||||||
|  |     GUI_SHOW_QWIDGET_TAB,           // param1=QWidget*,             param2=unused
 | ||||||
|  |     GUI_CLOSE_QWIDGET_TAB,          // param1=QWidget*,             param2=unused
 | ||||||
|  |     GUI_EXECUTE_ON_GUI_THREAD       // param1=GUICALLBACK,          param2=unused
 | ||||||
| } GUIMSG; | } GUIMSG; | ||||||
| 
 | 
 | ||||||
|  | //GUI Typedefs
 | ||||||
|  | typedef void (*GUICALLBACK)(); | ||||||
|  | 
 | ||||||
| //GUI structures
 | //GUI structures
 | ||||||
| typedef struct | typedef struct | ||||||
| { | { | ||||||
|  | @ -848,6 +855,10 @@ BRIDGE_IMPEXP void GuiLoadSourceFile(const char* path, int line); | ||||||
| BRIDGE_IMPEXP void GuiMenuSetIcon(int hMenu, const ICONDATA* icon); | BRIDGE_IMPEXP void GuiMenuSetIcon(int hMenu, const ICONDATA* icon); | ||||||
| BRIDGE_IMPEXP void GuiMenuSetEntryIcon(int hEntry, const ICONDATA* icon); | BRIDGE_IMPEXP void GuiMenuSetEntryIcon(int hEntry, const ICONDATA* icon); | ||||||
| BRIDGE_IMPEXP void GuiShowCpu(); | BRIDGE_IMPEXP void GuiShowCpu(); | ||||||
|  | BRIDGE_IMPEXP void GuiAddQWidgetTab(void* qWidget); | ||||||
|  | BRIDGE_IMPEXP void GuiShowQWidgetTab(void* qWidget); | ||||||
|  | BRIDGE_IMPEXP void GuiCloseQWidgetTab(void* qWidget); | ||||||
|  | BRIDGE_IMPEXP void GuiExecuteOnGuiThread(GUICALLBACK cbGuiThread); | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -109,7 +109,7 @@ | ||||||
|   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> |   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | ||||||
|     <ClCompile> |     <ClCompile> | ||||||
|       <PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> |       <PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||||
|       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> |       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> | ||||||
|       <WarningLevel>Level3</WarningLevel> |       <WarningLevel>Level3</WarningLevel> | ||||||
|       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> |       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> | ||||||
|       <Optimization>MaxSpeed</Optimization> |       <Optimization>MaxSpeed</Optimization> | ||||||
|  | @ -139,7 +139,7 @@ | ||||||
|   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> |   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | ||||||
|     <ClCompile> |     <ClCompile> | ||||||
|       <PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> |       <PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||||
|       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> |       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> | ||||||
|       <WarningLevel>Level3</WarningLevel> |       <WarningLevel>Level3</WarningLevel> | ||||||
|       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> |       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  |  | ||||||
|  | @ -17,6 +17,7 @@ | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <stack> | #include <stack> | ||||||
| #include <map> | #include <map> | ||||||
|  | #include <set> | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
| #include <unordered_map> | #include <unordered_map> | ||||||
| #include <tlhelp32.h> | #include <tlhelp32.h> | ||||||
|  |  | ||||||
|  | @ -0,0 +1,22 @@ | ||||||
|  | #include "_scriptapi_assembler.h" | ||||||
|  | #include "assemble.h" | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT bool Script::Assembler::Assemble(duint addr, unsigned char* dest, int* size, const char* instruction) | ||||||
|  | { | ||||||
|  |     return assemble(addr, dest, size, instruction, nullptr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT bool Script::Assembler::AssembleEx(duint addr, unsigned char* dest, int* size, const char* instruction, char* error) | ||||||
|  | { | ||||||
|  |     return assemble(addr, dest, size, instruction, error); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT bool Script::Assembler::AssembleMem(duint addr, const char* instruction) | ||||||
|  | { | ||||||
|  |     return assembleat(addr, instruction, nullptr, nullptr, false); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT bool Script::Assembler::AssembleMemEx(duint addr, const char* instruction, int* size, char* error, bool fillnop) | ||||||
|  | { | ||||||
|  |     return assembleat(addr, instruction, size, error, fillnop); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,17 @@ | ||||||
|  | #ifndef _SCRIPTAPI_ASSEMBLER_H | ||||||
|  | #define _SCRIPTAPI_ASSEMBLER_H | ||||||
|  | 
 | ||||||
|  | #include "_scriptapi.h" | ||||||
|  | 
 | ||||||
|  | namespace Script | ||||||
|  | { | ||||||
|  | namespace Assembler | ||||||
|  | { | ||||||
|  | SCRIPT_EXPORT bool Assemble(duint addr, unsigned char* dest, int* size, const char* instruction); //dest[16]
 | ||||||
|  | SCRIPT_EXPORT bool AssembleEx(duint addr, unsigned char* dest, int* size, const char* instruction, char* error); //dest[16], error[MAX_ERROR_SIZE]
 | ||||||
|  | SCRIPT_EXPORT bool AssembleMem(duint addr, const char* instruction); | ||||||
|  | SCRIPT_EXPORT bool AssembleMemEx(duint addr, const char* instruction, int* size, char* error, bool fillnop); //error[MAX_ERROR_SIZE]
 | ||||||
|  | }; //Assembler
 | ||||||
|  | }; //Script
 | ||||||
|  | 
 | ||||||
|  | #endif //_SCRIPTAPI_ASSEMBLER_H
 | ||||||
|  | @ -1,51 +1,5 @@ | ||||||
| #include "_scriptapi_gui.h" | #include "_scriptapi_gui.h" | ||||||
| 
 | #include "_scriptapi_misc.h" | ||||||
| static inline int windowToBridge(Script::Gui::Window window) |  | ||||||
| { |  | ||||||
|     switch(window) |  | ||||||
|     { |  | ||||||
|     case Script::Gui::DisassemblyWindow: |  | ||||||
|         return GUI_DISASSEMBLY; |  | ||||||
|     case Script::Gui::DumpWindow: |  | ||||||
|         return GUI_DUMP; |  | ||||||
|     case Script::Gui::StackWindow: |  | ||||||
|         return GUI_STACK; |  | ||||||
|     default: |  | ||||||
|         return GUI_DISASSEMBLY; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| SCRIPT_EXPORT bool Script::Gui::SelectionGet(Script::Gui::Window window, duint* start, duint* end) |  | ||||||
| { |  | ||||||
|     SELECTIONDATA selection; |  | ||||||
|     if(!GuiSelectionGet(windowToBridge(window), &selection)) |  | ||||||
|         return false; |  | ||||||
|     if(start) |  | ||||||
|         *start = selection.start; |  | ||||||
|     if(end) |  | ||||||
|         *end = selection.end; |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| SCRIPT_EXPORT bool Script::Gui::SelectionSet(Script::Gui::Window window, duint start, duint end) |  | ||||||
| { |  | ||||||
|     SELECTIONDATA selection; |  | ||||||
|     selection.start = start; |  | ||||||
|     selection.end = end; |  | ||||||
|     return GuiSelectionSet(windowToBridge(window), &selection); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| SCRIPT_EXPORT duint Script::Gui::SelectionGetStart(Script::Gui::Window window) |  | ||||||
| { |  | ||||||
|     duint start; |  | ||||||
|     return Gui::SelectionGet(window, &start, nullptr) ? start : 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| SCRIPT_EXPORT duint Script::Gui::SelectionGetEnd(Script::Gui::Window window) |  | ||||||
| { |  | ||||||
|     duint end; |  | ||||||
|     return Gui::SelectionGet(window, nullptr, &end) ? end : 0; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| SCRIPT_EXPORT bool Script::Gui::Disassembly::SelectionGet(duint* start, duint* end) | SCRIPT_EXPORT bool Script::Gui::Disassembly::SelectionGet(duint* start, duint* end) | ||||||
| { | { | ||||||
|  | @ -106,3 +60,93 @@ SCRIPT_EXPORT duint Script::Gui::Stack::SelectionGetEnd() | ||||||
| { | { | ||||||
|     return Gui::SelectionGetEnd(StackWindow); |     return Gui::SelectionGetEnd(StackWindow); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | static inline int windowToBridge(Script::Gui::Window window) | ||||||
|  | { | ||||||
|  |     switch(window) | ||||||
|  |     { | ||||||
|  |     case Script::Gui::DisassemblyWindow: | ||||||
|  |         return GUI_DISASSEMBLY; | ||||||
|  |     case Script::Gui::DumpWindow: | ||||||
|  |         return GUI_DUMP; | ||||||
|  |     case Script::Gui::StackWindow: | ||||||
|  |         return GUI_STACK; | ||||||
|  |     default: | ||||||
|  |         return GUI_DISASSEMBLY; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT bool Script::Gui::SelectionGet(Script::Gui::Window window, duint* start, duint* end) | ||||||
|  | { | ||||||
|  |     SELECTIONDATA selection; | ||||||
|  |     if(!GuiSelectionGet(windowToBridge(window), &selection)) | ||||||
|  |         return false; | ||||||
|  |     if(start) | ||||||
|  |         *start = selection.start; | ||||||
|  |     if(end) | ||||||
|  |         *end = selection.end; | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT bool Script::Gui::SelectionSet(Script::Gui::Window window, duint start, duint end) | ||||||
|  | { | ||||||
|  |     SELECTIONDATA selection; | ||||||
|  |     selection.start = start; | ||||||
|  |     selection.end = end; | ||||||
|  |     return GuiSelectionSet(windowToBridge(window), &selection); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT duint Script::Gui::SelectionGetStart(Script::Gui::Window window) | ||||||
|  | { | ||||||
|  |     duint start; | ||||||
|  |     return Gui::SelectionGet(window, &start, nullptr) ? start : 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT duint Script::Gui::SelectionGetEnd(Script::Gui::Window window) | ||||||
|  | { | ||||||
|  |     duint end; | ||||||
|  |     return Gui::SelectionGet(window, nullptr, &end) ? end : 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT void Script::Gui::Message(const char* message) | ||||||
|  | { | ||||||
|  |     GuiScriptMessage(message); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT bool Script::Gui::MessageYesNo(const char* message) | ||||||
|  | { | ||||||
|  |     return !!GuiScriptMsgyn(message); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT bool Script::Gui::InputLine(const char* title, char* text) | ||||||
|  | { | ||||||
|  |     return GuiGetLineWindow(title, text); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT bool Script::Gui::InputValue(const char* title, duint* value) | ||||||
|  | { | ||||||
|  |     Memory<char*> line(GUI_MAX_LINE_SIZE); | ||||||
|  |     if(!GuiGetLineWindow(title, line())) | ||||||
|  |         return false; | ||||||
|  |     return Misc::ParseExpression(line(), value); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT void Script::Gui::Refresh() | ||||||
|  | { | ||||||
|  |     GuiUpdateAllViews(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT void Script::Gui::AddQWidgetTab(void* qWidget) | ||||||
|  | { | ||||||
|  |     GuiAddQWidgetTab(qWidget); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT void Script::Gui::ShowQWidgetTab(void* qWidget) | ||||||
|  | { | ||||||
|  |     GuiShowQWidgetTab(qWidget); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT void Script::Gui::CloseQWidgetTab(void* qWidget) | ||||||
|  | { | ||||||
|  |     GuiCloseQWidgetTab(qWidget); | ||||||
|  | } | ||||||
|  | @ -7,18 +7,6 @@ namespace Script | ||||||
| { | { | ||||||
| namespace Gui | namespace Gui | ||||||
| { | { | ||||||
| enum Window |  | ||||||
| { |  | ||||||
|     DisassemblyWindow, |  | ||||||
|     DumpWindow, |  | ||||||
|     StackWindow |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| SCRIPT_EXPORT bool SelectionGet(Window window, duint* start, duint* end); |  | ||||||
| SCRIPT_EXPORT bool SelectionSet(Window window, duint start, duint end); |  | ||||||
| SCRIPT_EXPORT duint SelectionGetStart(Window window); |  | ||||||
| SCRIPT_EXPORT duint SelectionGetEnd(Window window); |  | ||||||
| 
 |  | ||||||
| namespace Disassembly | namespace Disassembly | ||||||
| { | { | ||||||
| SCRIPT_EXPORT bool SelectionGet(duint* start, duint* end); | SCRIPT_EXPORT bool SelectionGet(duint* start, duint* end); | ||||||
|  | @ -42,6 +30,30 @@ SCRIPT_EXPORT bool SelectionSet(duint start, duint end); | ||||||
| SCRIPT_EXPORT duint SelectionGetStart(); | SCRIPT_EXPORT duint SelectionGetStart(); | ||||||
| SCRIPT_EXPORT duint SelectionGetEnd(); | SCRIPT_EXPORT duint SelectionGetEnd(); | ||||||
| }; //Stack
 | }; //Stack
 | ||||||
|  | }; //Gui
 | ||||||
|  | 
 | ||||||
|  | namespace Gui | ||||||
|  | { | ||||||
|  | enum Window | ||||||
|  | { | ||||||
|  |     DisassemblyWindow, | ||||||
|  |     DumpWindow, | ||||||
|  |     StackWindow | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT bool SelectionGet(Window window, duint* start, duint* end); | ||||||
|  | SCRIPT_EXPORT bool SelectionSet(Window window, duint start, duint end); | ||||||
|  | SCRIPT_EXPORT duint SelectionGetStart(Window window); | ||||||
|  | SCRIPT_EXPORT duint SelectionGetEnd(Window window); | ||||||
|  | SCRIPT_EXPORT void Message(const char* message); | ||||||
|  | SCRIPT_EXPORT bool MessageYesNo(const char* message); | ||||||
|  | SCRIPT_EXPORT bool InputLine(const char* title, char* text); //text[GUI_MAX_LINE_SIZE]
 | ||||||
|  | SCRIPT_EXPORT bool InputValue(const char* title, duint* value); | ||||||
|  | SCRIPT_EXPORT void Refresh(); | ||||||
|  | SCRIPT_EXPORT void AddQWidgetTab(void* qWidget); | ||||||
|  | SCRIPT_EXPORT void ShowQWidgetTab(void* qWidget); | ||||||
|  | SCRIPT_EXPORT void CloseQWidgetTab(void* qWidget); | ||||||
|  | 
 | ||||||
| }; //Gui
 | }; //Gui
 | ||||||
| }; //Script
 | }; //Script
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,6 +11,21 @@ SCRIPT_EXPORT bool Script::Memory::Write(duint addr, const void* data, duint siz | ||||||
|     return MemWrite((void*)addr, (void*)data, size, sizeWritten); |     return MemWrite((void*)addr, (void*)data, size, sizeWritten); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | SCRIPT_EXPORT bool Script::Memory::IsValidPtr(duint addr) | ||||||
|  | { | ||||||
|  |     return MemIsValidReadPtr(addr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT duint Script::Memory::RemoteAlloc(duint addr, duint size) | ||||||
|  | { | ||||||
|  |     return (duint)MemAllocRemote(addr, size, PAGE_EXECUTE_READWRITE); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT bool Script::Memory::RemoteFree(duint addr) | ||||||
|  | { | ||||||
|  |     return MemFreeRemote(addr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| SCRIPT_EXPORT unsigned char Script::Memory::ReadByte(duint addr) | SCRIPT_EXPORT unsigned char Script::Memory::ReadByte(duint addr) | ||||||
| { | { | ||||||
|     unsigned char data; |     unsigned char data; | ||||||
|  |  | ||||||
|  | @ -9,6 +9,9 @@ namespace Memory | ||||||
| { | { | ||||||
| SCRIPT_EXPORT bool Read(duint addr, void* data, duint size, duint* sizeRead); | SCRIPT_EXPORT bool Read(duint addr, void* data, duint size, duint* sizeRead); | ||||||
| SCRIPT_EXPORT bool Write(duint addr, const void* data, duint size, duint* sizeWritten); | SCRIPT_EXPORT bool Write(duint addr, const void* data, duint size, duint* sizeWritten); | ||||||
|  | SCRIPT_EXPORT bool IsValidPtr(duint addr); | ||||||
|  | SCRIPT_EXPORT duint RemoteAlloc(duint addr, duint size); | ||||||
|  | SCRIPT_EXPORT bool RemoteFree(duint addr); | ||||||
| 
 | 
 | ||||||
| SCRIPT_EXPORT unsigned char ReadByte(duint addr); | SCRIPT_EXPORT unsigned char ReadByte(duint addr); | ||||||
| SCRIPT_EXPORT bool WriteByte(duint addr, unsigned char data); | SCRIPT_EXPORT bool WriteByte(duint addr, unsigned char data); | ||||||
|  |  | ||||||
|  | @ -0,0 +1,33 @@ | ||||||
|  | #include "_scriptapi_misc.h" | ||||||
|  | #include "value.h" | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT bool Script::Misc::ParseExpression(const char* expression, duint* value) | ||||||
|  | { | ||||||
|  |     return valfromstring(expression, value); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT duint Script::Misc::RemoteGetProcAddress(const char* module, const char* api) | ||||||
|  | { | ||||||
|  |     duint value; | ||||||
|  |     if(!ParseExpression(StringUtils::sprintf("%s:%s", module, api).c_str(), &value)) | ||||||
|  |         return 0; | ||||||
|  |     return value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT duint Script::Misc::ResolveLabel(const char* label) | ||||||
|  | { | ||||||
|  |     duint value; | ||||||
|  |     if(!ParseExpression(label, &value)) | ||||||
|  |         return 0; | ||||||
|  |     return value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT void* Script::Misc::Alloc(duint size) | ||||||
|  | { | ||||||
|  |     return emalloc(size, "Script::Misc::Alloc"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT void Script::Misc::Free(void* ptr) | ||||||
|  | { | ||||||
|  |     return efree(ptr, "Script::Misc::Free"); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | #ifndef _SCRIPTAPI_MISC_H | ||||||
|  | #define _SCRIPTAPI_MISC_H | ||||||
|  | 
 | ||||||
|  | #include "_scriptapi.h" | ||||||
|  | 
 | ||||||
|  | namespace Script | ||||||
|  | { | ||||||
|  | namespace Misc | ||||||
|  | { | ||||||
|  | SCRIPT_EXPORT bool ParseExpression(const char* expression, duint* value); | ||||||
|  | SCRIPT_EXPORT duint RemoteGetProcAddress(const char* module, const char* api); | ||||||
|  | SCRIPT_EXPORT duint ResolveLabel(const char* label); | ||||||
|  | SCRIPT_EXPORT void* Alloc(duint size); | ||||||
|  | SCRIPT_EXPORT void Free(void* ptr); | ||||||
|  | }; //Misc
 | ||||||
|  | }; //Script
 | ||||||
|  | 
 | ||||||
|  | #endif //_SCRIPTAPI_MISC_H
 | ||||||
|  | @ -9,6 +9,7 @@ static const char* regTable[] = | ||||||
|     "DR3", |     "DR3", | ||||||
|     "DR6", |     "DR6", | ||||||
|     "DR7", |     "DR7", | ||||||
|  | 
 | ||||||
|     "EAX", |     "EAX", | ||||||
|     "AX", |     "AX", | ||||||
|     "AH", |     "AH", | ||||||
|  | @ -34,7 +35,7 @@ static const char* regTable[] = | ||||||
|     "ESP", |     "ESP", | ||||||
|     "SP", |     "SP", | ||||||
|     "EIP", |     "EIP", | ||||||
|     "CIP", | 
 | ||||||
| #ifdef _WIN64 | #ifdef _WIN64 | ||||||
|     "RAX", |     "RAX", | ||||||
|     "RBX", |     "RBX", | ||||||
|  | @ -80,7 +81,15 @@ static const char* regTable[] = | ||||||
|     "R15", |     "R15", | ||||||
|     "R15D", |     "R15D", | ||||||
|     "R15W", |     "R15W", | ||||||
|     "R15" |     "R15", | ||||||
|  | #endif //_WIN64
 | ||||||
|  | 
 | ||||||
|  | #ifdef _WIN64 | ||||||
|  |     "RIP", | ||||||
|  |     "RSP" | ||||||
|  | #else //x32
 | ||||||
|  |     "EIP", | ||||||
|  |     "ESP" | ||||||
| #endif //_WIN64
 | #endif //_WIN64
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -96,6 +105,11 @@ SCRIPT_EXPORT bool Script::Register::Set(Script::Register::RegisterEnum reg, dui | ||||||
|     return setregister(regTable[reg], value); |     return setregister(regTable[reg], value); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | SCRIPT_EXPORT int Script::Register::Size() | ||||||
|  | { | ||||||
|  |     return (int)sizeof(duint); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| SCRIPT_EXPORT duint Script::Register::GetDR0() | SCRIPT_EXPORT duint Script::Register::GetDR0() | ||||||
| { | { | ||||||
|     return Get(DR0); |     return Get(DR0); | ||||||
|  | @ -406,16 +420,6 @@ SCRIPT_EXPORT bool Script::Register::SetEIP(unsigned int value) | ||||||
|     return Set(EIP, value); |     return Set(EIP, value); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| SCRIPT_EXPORT duint Script::Register::GetCIP() |  | ||||||
| { |  | ||||||
|     return Get(CIP); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| SCRIPT_EXPORT bool Script::Register::SetCIP(duint value) |  | ||||||
| { |  | ||||||
|     return Set(CIP, value); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #ifdef _WIN64 | #ifdef _WIN64 | ||||||
| SCRIPT_EXPORT unsigned long long Script::Register::GetRAX() | SCRIPT_EXPORT unsigned long long Script::Register::GetRAX() | ||||||
| { | { | ||||||
|  | @ -867,3 +871,23 @@ SCRIPT_EXPORT bool Script::Register::SetR15B(unsigned char value) | ||||||
|     return Set(R15B, value); |     return Set(R15B, value); | ||||||
| } | } | ||||||
| #endif //_WIN64
 | #endif //_WIN64
 | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT duint Script::Register::GetCIP() | ||||||
|  | { | ||||||
|  |     return Get(CIP); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT bool Script::Register::SetCIP(duint value) | ||||||
|  | { | ||||||
|  |     return Set(CIP, value); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT duint Script::Register::GetCSP() | ||||||
|  | { | ||||||
|  |     return Get(CSP); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT bool Script::Register::SetCSP(duint value) | ||||||
|  | { | ||||||
|  |     return Set(CSP, value); | ||||||
|  | } | ||||||
|  | @ -15,6 +15,7 @@ enum RegisterEnum | ||||||
|     DR3, |     DR3, | ||||||
|     DR6, |     DR6, | ||||||
|     DR7, |     DR7, | ||||||
|  | 
 | ||||||
|     EAX, |     EAX, | ||||||
|     AX, |     AX, | ||||||
|     AH, |     AH, | ||||||
|  | @ -40,7 +41,7 @@ enum RegisterEnum | ||||||
|     ESP, |     ESP, | ||||||
|     SP, |     SP, | ||||||
|     EIP, |     EIP, | ||||||
|     CIP, | 
 | ||||||
| #ifdef _WIN64 | #ifdef _WIN64 | ||||||
|     RAX, |     RAX, | ||||||
|     RBX, |     RBX, | ||||||
|  | @ -86,12 +87,16 @@ enum RegisterEnum | ||||||
|     R15, |     R15, | ||||||
|     R15D, |     R15D, | ||||||
|     R15W, |     R15W, | ||||||
|     R15B |     R15B, | ||||||
| #endif //_WIN64
 | #endif //_WIN64
 | ||||||
|  | 
 | ||||||
|  |     CIP, | ||||||
|  |     CSP, | ||||||
| }; //RegisterEnum
 | }; //RegisterEnum
 | ||||||
| 
 | 
 | ||||||
| SCRIPT_EXPORT duint Get(RegisterEnum reg); | SCRIPT_EXPORT duint Get(RegisterEnum reg); | ||||||
| SCRIPT_EXPORT bool Set(RegisterEnum reg, duint value); | SCRIPT_EXPORT bool Set(RegisterEnum reg, duint value); | ||||||
|  | SCRIPT_EXPORT int Size(); //gets architecture register size in bytes
 | ||||||
| 
 | 
 | ||||||
| SCRIPT_EXPORT duint GetDR0(); | SCRIPT_EXPORT duint GetDR0(); | ||||||
| SCRIPT_EXPORT bool SetDR0(duint value); | SCRIPT_EXPORT bool SetDR0(duint value); | ||||||
|  | @ -105,6 +110,7 @@ SCRIPT_EXPORT duint GetDR6(); | ||||||
| SCRIPT_EXPORT bool SetDR6(duint value); | SCRIPT_EXPORT bool SetDR6(duint value); | ||||||
| SCRIPT_EXPORT duint GetDR7(); | SCRIPT_EXPORT duint GetDR7(); | ||||||
| SCRIPT_EXPORT bool SetDR7(duint value); | SCRIPT_EXPORT bool SetDR7(duint value); | ||||||
|  | 
 | ||||||
| SCRIPT_EXPORT unsigned int GetEAX(); | SCRIPT_EXPORT unsigned int GetEAX(); | ||||||
| SCRIPT_EXPORT bool SetEAX(unsigned int value); | SCRIPT_EXPORT bool SetEAX(unsigned int value); | ||||||
| SCRIPT_EXPORT unsigned short GetAX(); | SCRIPT_EXPORT unsigned short GetAX(); | ||||||
|  | @ -155,8 +161,7 @@ SCRIPT_EXPORT unsigned short GetSP(); | ||||||
| SCRIPT_EXPORT bool SetSP(unsigned short value); | SCRIPT_EXPORT bool SetSP(unsigned short value); | ||||||
| SCRIPT_EXPORT unsigned int GetEIP(); | SCRIPT_EXPORT unsigned int GetEIP(); | ||||||
| SCRIPT_EXPORT bool SetEIP(unsigned int value); | SCRIPT_EXPORT bool SetEIP(unsigned int value); | ||||||
| SCRIPT_EXPORT duint GetCIP(); | 
 | ||||||
| SCRIPT_EXPORT bool SetCIP(duint value); |  | ||||||
| #ifdef _WIN64 | #ifdef _WIN64 | ||||||
| SCRIPT_EXPORT unsigned long long GetRAX(); | SCRIPT_EXPORT unsigned long long GetRAX(); | ||||||
| SCRIPT_EXPORT bool SetRAX(unsigned long long value); | SCRIPT_EXPORT bool SetRAX(unsigned long long value); | ||||||
|  | @ -249,6 +254,11 @@ SCRIPT_EXPORT bool SetR15W(unsigned short value); | ||||||
| SCRIPT_EXPORT unsigned char GetR15B(); | SCRIPT_EXPORT unsigned char GetR15B(); | ||||||
| SCRIPT_EXPORT bool SetR15B(unsigned char value); | SCRIPT_EXPORT bool SetR15B(unsigned char value); | ||||||
| #endif //_WIN64
 | #endif //_WIN64
 | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT duint GetCIP(); | ||||||
|  | SCRIPT_EXPORT bool SetCIP(duint value); | ||||||
|  | SCRIPT_EXPORT duint GetCSP(); | ||||||
|  | SCRIPT_EXPORT bool SetCSP(duint value); | ||||||
| }; //Register
 | }; //Register
 | ||||||
| }; //Script
 | }; //Script
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,24 @@ | ||||||
|  | #include "_scriptapi_stack.h" | ||||||
|  | #include "_scriptapi_memory.h" | ||||||
|  | #include "_scriptapi_register.h" | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT duint Script::Stack::Pop() | ||||||
|  | { | ||||||
|  |     duint csp = Register::GetCSP(); | ||||||
|  |     duint top = Memory::ReadPtr(csp); | ||||||
|  |     Register::SetCSP(csp + sizeof(duint)); | ||||||
|  |     return top; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT duint Script::Stack::Push(duint value) | ||||||
|  | { | ||||||
|  |     duint csp = Register::GetCSP(); | ||||||
|  |     Register::SetCSP(csp - sizeof(duint)); | ||||||
|  |     Memory::WritePtr(csp, value); | ||||||
|  |     return Memory::ReadPtr(csp); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SCRIPT_EXPORT duint Script::Stack::Peek(int offset) | ||||||
|  | { | ||||||
|  |     return Memory::ReadPtr(Register::GetCSP() + offset * sizeof(duint)); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,16 @@ | ||||||
|  | #ifndef _SCRIPTAPI_STACK_H | ||||||
|  | #define _SCRIPTAPI_STACK_H | ||||||
|  | 
 | ||||||
|  | #include "_scriptapi.h" | ||||||
|  | 
 | ||||||
|  | namespace Script | ||||||
|  | { | ||||||
|  | namespace Stack | ||||||
|  | { | ||||||
|  | SCRIPT_EXPORT duint Pop(); | ||||||
|  | SCRIPT_EXPORT duint Push(duint value); //returns the previous top, equal to Peek(1)
 | ||||||
|  | SCRIPT_EXPORT duint Peek(int offset = 0); //offset is in multiples of Register::Size(), for easy x32/x64 portability
 | ||||||
|  | }; //Stack
 | ||||||
|  | }; //Script
 | ||||||
|  | 
 | ||||||
|  | #endif //_SCRIPTAPI_STACK_H
 | ||||||
|  | @ -0,0 +1,25 @@ | ||||||
|  | #include "analysis.h" | ||||||
|  | #include "memory.h" | ||||||
|  | 
 | ||||||
|  | Analysis::Analysis(uint base, uint size) | ||||||
|  | { | ||||||
|  |     _base = base; | ||||||
|  |     _size = size; | ||||||
|  |     _data = new unsigned char[_size + MAX_DISASM_BUFFER]; | ||||||
|  |     MemRead((void*)_base, _data, _size, 0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Analysis::~Analysis() | ||||||
|  | { | ||||||
|  |     delete[] _data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool Analysis::IsValidAddress(uint addr) | ||||||
|  | { | ||||||
|  |     return addr >= _base && addr < _base + _size; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const unsigned char* Analysis::TranslateAddress(uint addr) | ||||||
|  | { | ||||||
|  |     return IsValidAddress(addr) ? _data + (addr - _base) : nullptr; | ||||||
|  | } | ||||||
|  | @ -0,0 +1,26 @@ | ||||||
|  | #ifndef _ANALYSIS_H | ||||||
|  | #define _ANALYSIS_H | ||||||
|  | 
 | ||||||
|  | #include "_global.h" | ||||||
|  | #include "capstone_wrapper.h" | ||||||
|  | 
 | ||||||
|  | class Analysis | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |     explicit Analysis(uint base, uint size); | ||||||
|  |     Analysis(const Analysis & that) = delete; | ||||||
|  |     ~Analysis(); | ||||||
|  |     virtual void Analyse() = 0; | ||||||
|  |     virtual void SetMarkers() = 0; | ||||||
|  | 
 | ||||||
|  | protected: | ||||||
|  |     uint _base; | ||||||
|  |     uint _size; | ||||||
|  |     unsigned char* _data; | ||||||
|  |     Capstone _cp; | ||||||
|  | 
 | ||||||
|  |     bool IsValidAddress(uint addr); | ||||||
|  |     const unsigned char* TranslateAddress(uint addr); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif //_ANALYSIS_H
 | ||||||
|  | @ -86,7 +86,7 @@ String Capstone::OperandText(int opindex) | ||||||
| 
 | 
 | ||||||
|     case X86_OP_IMM: |     case X86_OP_IMM: | ||||||
|     { |     { | ||||||
|         if(InGroup(CS_GRP_JUMP) || InGroup(CS_GRP_CALL)) |         if(InGroup(CS_GRP_JUMP) || InGroup(CS_GRP_CALL) || IsLoop()) | ||||||
|             sprintf_s(temp, "%"fext"X", op.imm + mInstr->size); |             sprintf_s(temp, "%"fext"X", op.imm + mInstr->size); | ||||||
|         else |         else | ||||||
|             sprintf_s(temp, "%"fext"X", op.imm); |             sprintf_s(temp, "%"fext"X", op.imm); | ||||||
|  | @ -163,8 +163,27 @@ const cs_x86 & Capstone::x86() | ||||||
| 
 | 
 | ||||||
| bool Capstone::IsFilling() | bool Capstone::IsFilling() | ||||||
| { | { | ||||||
|     uint8_t opcode = x86().opcode[0]; |     switch(GetId()) | ||||||
|     return opcode == 0x90 || opcode == 0xCC; |     { | ||||||
|  |     case X86_INS_NOP: | ||||||
|  |     case X86_INS_INT3: | ||||||
|  |         return true; | ||||||
|  |     default: | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool Capstone::IsLoop() | ||||||
|  | { | ||||||
|  |     switch(GetId()) | ||||||
|  |     { | ||||||
|  |     case X86_INS_LOOP: | ||||||
|  |     case X86_INS_LOOPE: | ||||||
|  |     case X86_INS_LOOPNE: | ||||||
|  |         return true; | ||||||
|  |     default: | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| x86_insn Capstone::GetId() | x86_insn Capstone::GetId() | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ public: | ||||||
|     const uint Address(); |     const uint Address(); | ||||||
|     const cs_x86 & x86(); |     const cs_x86 & x86(); | ||||||
|     bool IsFilling(); |     bool IsFilling(); | ||||||
|  |     bool IsLoop(); | ||||||
|     x86_insn GetId(); |     x86_insn GetId(); | ||||||
|     String InstructionText(); |     String InstructionText(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,168 @@ | ||||||
|  | #include "controlflowanalysis.h" | ||||||
|  | #include "memory.h" | ||||||
|  | #include "console.h" | ||||||
|  | 
 | ||||||
|  | ControlFlowAnalysis::ControlFlowAnalysis(uint base, uint size) : Analysis(base, size) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ControlFlowAnalysis::Analyse() | ||||||
|  | { | ||||||
|  |     dputs("Starting analysis..."); | ||||||
|  |     DWORD ticks = GetTickCount(); | ||||||
|  | 
 | ||||||
|  |     BasicBlockStarts(); | ||||||
|  |     BasicBlocks(); | ||||||
|  | 
 | ||||||
|  |     dprintf("Analysis finished in %ums!\n", GetTickCount() - ticks); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ControlFlowAnalysis::SetMarkers() | ||||||
|  | { | ||||||
|  |     dprintf("digraph ControlFlow {\n"); | ||||||
|  |     int i = 0; | ||||||
|  |     std::map<uint, int> nodeMap; | ||||||
|  |     for(auto block : _blocks) | ||||||
|  |     { | ||||||
|  |         nodeMap.insert({ block.start, i }); | ||||||
|  |         dprintf("    node%u [label=\"start=%p, end=%p\"];\n", i, block.start, block.end); | ||||||
|  |         i++; | ||||||
|  |     } | ||||||
|  |     for(auto block : _blocks) | ||||||
|  |     { | ||||||
|  |         int startNode = nodeMap[block.start]; | ||||||
|  |         if(block.left) | ||||||
|  |         { | ||||||
|  |             if(nodeMap.count(block.left)) | ||||||
|  |                 dprintf("    node%u -> node%u;\n", startNode, nodeMap[block.left]); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             dprintf("    node%u [shape=point];\n", i); | ||||||
|  |             dprintf("    node%u -> node%u;\n", startNode, i); | ||||||
|  |             i++; | ||||||
|  |         } | ||||||
|  |         if(block.right) | ||||||
|  |         { | ||||||
|  |             if(nodeMap.count(block.right)) | ||||||
|  |                 dprintf("    node%u -> node%u;\n", startNode, nodeMap[block.right]); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             dprintf("    node%u [shape=point];\n", i); | ||||||
|  |             dprintf("    node%u -> node%u;\n", startNode, i); | ||||||
|  |             i++; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     dprintf("}\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ControlFlowAnalysis::BasicBlockStarts() | ||||||
|  | { | ||||||
|  |     _blockStarts.insert(_base); | ||||||
|  |     bool bSkipFilling = false; | ||||||
|  |     for(uint i = 0; i < _size;) | ||||||
|  |     { | ||||||
|  |         uint addr = _base + i; | ||||||
|  |         if(_cp.Disassemble(addr, TranslateAddress(addr), MAX_DISASM_BUFFER)) | ||||||
|  |         { | ||||||
|  |             if(bSkipFilling)  //handle filling skip mode
 | ||||||
|  |             { | ||||||
|  |                 if(!_cp.IsFilling())  //do nothing until the filling stopped
 | ||||||
|  |                 { | ||||||
|  |                     bSkipFilling = false; | ||||||
|  |                     _blockStarts.insert(addr); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else if(_cp.InGroup(CS_GRP_RET) || _cp.InGroup(CS_GRP_INT)) //RET/INT break control flow
 | ||||||
|  |             { | ||||||
|  |                 bSkipFilling = true; //skip INT3/NOP/whatever filling bytes (those are not part of the control flow)
 | ||||||
|  |             } | ||||||
|  |             else if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop())  //branches
 | ||||||
|  |             { | ||||||
|  |                 uint dest1 = GetBranchOperand(); | ||||||
|  |                 uint dest2 = 0; | ||||||
|  |                 if(_cp.GetId() != X86_INS_JMP)   //unconditional jump
 | ||||||
|  |                     dest2 = addr + _cp.Size(); | ||||||
|  | 
 | ||||||
|  |                 if(!dest1 && !dest2) //TODO: better code for this (make sure absolutely no filling is inserted)
 | ||||||
|  |                     bSkipFilling = true; | ||||||
|  |                 if(dest1) | ||||||
|  |                     _blockStarts.insert(dest1); | ||||||
|  |                 if(dest2) | ||||||
|  |                     _blockStarts.insert(dest2); | ||||||
|  |             } | ||||||
|  |             else if(_cp.InGroup(CS_GRP_CALL)) | ||||||
|  |             { | ||||||
|  |                 uint dest1 = GetBranchOperand(); | ||||||
|  |                 if(dest1) | ||||||
|  |                     _blockStarts.insert(dest1); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 uint dest1 = GetBranchOperand(); | ||||||
|  |                 if(dest1) | ||||||
|  |                     _blockStarts.insert(dest1); | ||||||
|  |             } | ||||||
|  |             i += _cp.Size(); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |             i++; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ControlFlowAnalysis::BasicBlocks() | ||||||
|  | { | ||||||
|  |     for(auto i = _blockStarts.begin(); i != _blockStarts.end(); i++) | ||||||
|  |     { | ||||||
|  |         uint start = *i; | ||||||
|  |         if(!IsValidAddress(start)) | ||||||
|  |             continue; | ||||||
|  |         uint nextStart = _base + _size; | ||||||
|  |         auto next = std::next(i); | ||||||
|  |         if(next != _blockStarts.end()) | ||||||
|  |             nextStart = *next; | ||||||
|  |         for(uint addr = start, prevaddr = 0; addr < _base + _size;) | ||||||
|  |         { | ||||||
|  |             prevaddr = addr; | ||||||
|  |             if(_cp.Disassemble(addr, TranslateAddress(addr), MAX_DISASM_BUFFER)) | ||||||
|  |             { | ||||||
|  |                 if(_cp.InGroup(CS_GRP_RET)) | ||||||
|  |                 { | ||||||
|  |                     _blocks.push_back(BasicBlock(start, addr, 0, 0)); //leaf block
 | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 else if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop()) | ||||||
|  |                 { | ||||||
|  |                     uint dest1 = GetBranchOperand(); | ||||||
|  |                     uint dest2 = _cp.GetId() != X86_INS_JMP ? addr + _cp.Size() : 0; | ||||||
|  |                     _blocks.push_back(BasicBlock(start, addr, dest1, dest2)); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 addr += _cp.Size(); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |                 addr++; | ||||||
|  |             if(addr == nextStart)  //special case handling overlapping blocks
 | ||||||
|  |             { | ||||||
|  |                 _blocks.push_back(BasicBlock(start, prevaddr, 0, nextStart)); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint ControlFlowAnalysis::GetBranchOperand() | ||||||
|  | { | ||||||
|  |     for(int i = 0; i < _cp.x86().op_count; i++) | ||||||
|  |     { | ||||||
|  |         const cs_x86_op & operand = _cp.x86().operands[i]; | ||||||
|  |         if(operand.type == X86_OP_IMM) | ||||||
|  |         { | ||||||
|  |             uint dest = (uint)operand.imm; | ||||||
|  |             if(dest >= _base && dest < _base + _size) | ||||||
|  |                 return dest; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | @ -0,0 +1,48 @@ | ||||||
|  | #ifndef _CONTROLFLOWANALYSIS_H | ||||||
|  | #define _CONTROLFLOWANALYSIS_H | ||||||
|  | 
 | ||||||
|  | #include "_global.h" | ||||||
|  | #include "capstone_wrapper.h" | ||||||
|  | #include "analysis.h" | ||||||
|  | 
 | ||||||
|  | class ControlFlowAnalysis : public Analysis | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |     explicit ControlFlowAnalysis(uint base, uint size); | ||||||
|  |     void Analyse(); | ||||||
|  |     void SetMarkers(); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     struct BasicBlock | ||||||
|  |     { | ||||||
|  |         uint start; | ||||||
|  |         uint end; | ||||||
|  |         uint left; | ||||||
|  |         uint right; | ||||||
|  | 
 | ||||||
|  |         BasicBlock() | ||||||
|  |         { | ||||||
|  |             this->start = 0; | ||||||
|  |             this->end = 0; | ||||||
|  |             this->left = 0; | ||||||
|  |             this->right = 0; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         BasicBlock(uint start, uint end, uint left, uint right) | ||||||
|  |         { | ||||||
|  |             this->start = start; | ||||||
|  |             this->end = end; | ||||||
|  |             this->left = min(left, right); | ||||||
|  |             this->right = max(left, right); | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     std::set<uint> _blockStarts; | ||||||
|  |     std::vector<BasicBlock> _blocks; | ||||||
|  | 
 | ||||||
|  |     void BasicBlockStarts(); | ||||||
|  |     void BasicBlocks(); | ||||||
|  |     uint GetBranchOperand(); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif //_CONTROLFLOWANALYSIS_H
 | ||||||
|  | @ -776,14 +776,16 @@ static void cbExitThread(EXIT_THREAD_DEBUG_INFO* ExitThread) | ||||||
| static void cbSystemBreakpoint(void* ExceptionData) | static void cbSystemBreakpoint(void* ExceptionData) | ||||||
| { | { | ||||||
|     hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId); |     hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId); | ||||||
|  | 
 | ||||||
|  |     uint cip = GetContextDataEx(hActiveThread, UE_CIP); | ||||||
|  |     GuiDumpAt(MemFindBaseAddr(cip, 0, true)); //dump somewhere
 | ||||||
|  | 
 | ||||||
|     //log message
 |     //log message
 | ||||||
|     if(bIsAttached) |     if(bIsAttached) | ||||||
|         dputs("Attach breakpoint reached!"); |         dputs("Attach breakpoint reached!"); | ||||||
|     else |     else | ||||||
|         dputs("System breakpoint reached!"); |         dputs("System breakpoint reached!"); | ||||||
|     bSkipExceptions = false; //we are not skipping first-chance exceptions
 |     bSkipExceptions = false; //we are not skipping first-chance exceptions
 | ||||||
|     uint cip = GetContextDataEx(hActiveThread, UE_CIP); |  | ||||||
|     GuiDumpAt(MemFindBaseAddr(cip, 0, true)); //dump somewhere
 |  | ||||||
| 
 | 
 | ||||||
|     //plugin callbacks
 |     //plugin callbacks
 | ||||||
|     PLUG_CB_SYSTEMBREAKPOINT callbackInfo; |     PLUG_CB_SYSTEMBREAKPOINT callbackInfo; | ||||||
|  |  | ||||||
|  | @ -38,7 +38,7 @@ void fillbasicinfo(Capstone* cp, BASIC_INSTRUCTION_INFO* basicinfo) | ||||||
|         basicinfo->branch = true; |         basicinfo->branch = true; | ||||||
|         basicinfo->call = true; |         basicinfo->call = true; | ||||||
|     } |     } | ||||||
|     else if(cp->InGroup(CS_GRP_JUMP)) |     else if(cp->InGroup(CS_GRP_JUMP) || cp->IsLoop()) | ||||||
|     { |     { | ||||||
|         basicinfo->branch = true; |         basicinfo->branch = true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -204,7 +204,7 @@ void disasmget(unsigned char* buffer, uint addr, DISASM_INSTR* instr) | ||||||
|     sprintf_s(instr->instruction, "%s %s", cp.GetInstr()->mnemonic, cp.GetInstr()->op_str); |     sprintf_s(instr->instruction, "%s %s", cp.GetInstr()->mnemonic, cp.GetInstr()->op_str); | ||||||
|     const cs_x86 & x86 = cp.GetInstr()->detail->x86; |     const cs_x86 & x86 = cp.GetInstr()->detail->x86; | ||||||
|     instr->instr_size = cp.GetInstr()->size; |     instr->instr_size = cp.GetInstr()->size; | ||||||
|     if(cp.InGroup(CS_GRP_JUMP) || cp.InGroup(CS_GRP_RET) || cp.InGroup(CS_GRP_CALL)) |     if(cp.InGroup(CS_GRP_JUMP) || cp.IsLoop() || cp.InGroup(CS_GRP_RET) || cp.InGroup(CS_GRP_CALL)) | ||||||
|         instr->type = instr_branch; |         instr->type = instr_branch; | ||||||
|     else if(strstr(cp.GetInstr()->op_str, "sp") || strstr(cp.GetInstr()->op_str, "bp")) |     else if(strstr(cp.GetInstr()->op_str, "sp") || strstr(cp.GetInstr()->op_str, "bp")) | ||||||
|         instr->type = instr_stack; |         instr->type = instr_stack; | ||||||
|  |  | ||||||
|  | @ -3,31 +3,20 @@ | ||||||
| #include "memory.h" | #include "memory.h" | ||||||
| #include "function.h" | #include "function.h" | ||||||
| 
 | 
 | ||||||
| #include "module.h" | FunctionAnalysis::FunctionAnalysis(uint base, uint size) : Analysis(base, size) | ||||||
| #include "LinearPass.h" |  | ||||||
| 
 |  | ||||||
| FunctionAnalysis::FunctionAnalysis(uint base, uint size) |  | ||||||
| { | { | ||||||
|     _base = base; |  | ||||||
|     _size = size; |  | ||||||
|     _data = new unsigned char[_size + MAX_DISASM_BUFFER]; |  | ||||||
|     MemRead((void*)_base, _data, _size, 0); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| FunctionAnalysis::~FunctionAnalysis() |  | ||||||
| { |  | ||||||
|     delete[] _data; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const unsigned char* FunctionAnalysis::TranslateAddress(uint addr) |  | ||||||
| { |  | ||||||
|     return (addr >= _base && addr < _base + _size) ? _data + (addr - _base) : nullptr; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void Derp(uint _base); |  | ||||||
| void FunctionAnalysis::Analyse() | void FunctionAnalysis::Analyse() | ||||||
| { | { | ||||||
|     Derp(_base); |     dputs("Starting analysis..."); | ||||||
|  |     DWORD ticks = GetTickCount(); | ||||||
|  | 
 | ||||||
|  |     PopulateReferences(); | ||||||
|  |     dprintf("%u called functions populated\n", _functions.size()); | ||||||
|  |     AnalyseFunctions(); | ||||||
|  | 
 | ||||||
|  |     dprintf("Analysis finished in %ums!\n", GetTickCount() - ticks); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void FunctionAnalysis::SetMarkers() | void FunctionAnalysis::SetMarkers() | ||||||
|  | @ -109,7 +98,7 @@ uint FunctionAnalysis::FindFunctionEnd(uint start, uint maxaddr) | ||||||
|                 break; |                 break; | ||||||
| 
 | 
 | ||||||
|             const cs_x86_op & operand = _cp.x86().operands[0]; |             const cs_x86_op & operand = _cp.x86().operands[0]; | ||||||
|             if(_cp.InGroup(CS_GRP_JUMP) && operand.type == X86_OP_IMM)   //jump
 |             if((_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop()) && operand.type == X86_OP_IMM)   //jump
 | ||||||
|             { |             { | ||||||
|                 uint dest = (uint)operand.imm; |                 uint dest = (uint)operand.imm; | ||||||
| 
 | 
 | ||||||
|  | @ -121,7 +110,7 @@ uint FunctionAnalysis::FindFunctionEnd(uint start, uint maxaddr) | ||||||
|                 { |                 { | ||||||
|                     fardest = dest; |                     fardest = dest; | ||||||
|                 } |                 } | ||||||
|                 else if(end && dest < end && _cp.GetId() == X86_INS_JMP)   //save the last JMP backwards
 |                 else if(end && dest < end && (_cp.GetId() == X86_INS_JMP || _cp.GetId() == X86_INS_LOOP)) //save the last JMP backwards
 | ||||||
|                 { |                 { | ||||||
|                     jumpback = addr; |                     jumpback = addr; | ||||||
|                 } |                 } | ||||||
|  | @ -146,7 +135,7 @@ uint FunctionAnalysis::GetReferenceOperand() | ||||||
|     for(int i = 0; i < _cp.x86().op_count; i++) |     for(int i = 0; i < _cp.x86().op_count; i++) | ||||||
|     { |     { | ||||||
|         const cs_x86_op & operand = _cp.x86().operands[i]; |         const cs_x86_op & operand = _cp.x86().operands[i]; | ||||||
|         if(_cp.InGroup(CS_GRP_JUMP))  //skip jumps
 |         if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop())  //skip jumps/loops
 | ||||||
|             continue; |             continue; | ||||||
|         if(operand.type == X86_OP_IMM)  //we are looking for immediate references
 |         if(operand.type == X86_OP_IMM)  //we are looking for immediate references
 | ||||||
|         { |         { | ||||||
|  |  | ||||||
|  | @ -3,17 +3,16 @@ | ||||||
| 
 | 
 | ||||||
| #include "_global.h" | #include "_global.h" | ||||||
| #include "capstone_wrapper.h" | #include "capstone_wrapper.h" | ||||||
|  | #include "analysis.h" | ||||||
| 
 | 
 | ||||||
| class FunctionAnalysis | class FunctionAnalysis : public Analysis | ||||||
| { | { | ||||||
| public: | public: | ||||||
|     explicit FunctionAnalysis(uint base, uint size); |     explicit FunctionAnalysis(uint base, uint size); | ||||||
|     FunctionAnalysis(const FunctionAnalysis & that) = delete; |  | ||||||
|     ~FunctionAnalysis(); |  | ||||||
|     const unsigned char* TranslateAddress(uint addr); |  | ||||||
|     void Analyse(); |     void Analyse(); | ||||||
|     void SetMarkers(); |     void SetMarkers(); | ||||||
| 
 | 
 | ||||||
|  | private: | ||||||
|     struct FunctionInfo |     struct FunctionInfo | ||||||
|     { |     { | ||||||
|         uint start; |         uint start; | ||||||
|  | @ -30,12 +29,7 @@ public: | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| private: |  | ||||||
|     uint _base; |  | ||||||
|     uint _size; |  | ||||||
|     unsigned char* _data; |  | ||||||
|     std::vector<FunctionInfo> _functions; |     std::vector<FunctionInfo> _functions; | ||||||
|     Capstone _cp; |  | ||||||
| 
 | 
 | ||||||
|     void SortCleanup(); |     void SortCleanup(); | ||||||
|     void PopulateReferences(); |     void PopulateReferences(); | ||||||
|  |  | ||||||
|  | @ -26,6 +26,8 @@ | ||||||
| #include "module.h" | #include "module.h" | ||||||
| #include "stringformat.h" | #include "stringformat.h" | ||||||
| #include "filereader.h" | #include "filereader.h" | ||||||
|  | #include "functionanalysis.h" | ||||||
|  | #include "controlflowanalysis.h" | ||||||
| 
 | 
 | ||||||
| static bool bRefinit = false; | static bool bRefinit = false; | ||||||
| 
 | 
 | ||||||
|  | @ -1877,8 +1879,6 @@ CMDRESULT cbInstrCapstone(int argc, char* argv[]) | ||||||
|     return STATUS_CONTINUE; |     return STATUS_CONTINUE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #include "functionanalysis.h" |  | ||||||
| 
 |  | ||||||
| CMDRESULT cbInstrAnalyse(int argc, char* argv[]) | CMDRESULT cbInstrAnalyse(int argc, char* argv[]) | ||||||
| { | { | ||||||
|     SELECTIONDATA sel; |     SELECTIONDATA sel; | ||||||
|  | @ -1892,6 +1892,19 @@ CMDRESULT cbInstrAnalyse(int argc, char* argv[]) | ||||||
|     return STATUS_CONTINUE; |     return STATUS_CONTINUE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | CMDRESULT cbInstrCfanalyse(int argc, char* argv[]) | ||||||
|  | { | ||||||
|  |     SELECTIONDATA sel; | ||||||
|  |     GuiSelectionGet(GUI_DISASSEMBLY, &sel); | ||||||
|  |     uint size = 0; | ||||||
|  |     uint base = MemFindBaseAddr(sel.start, &size); | ||||||
|  |     ControlFlowAnalysis anal(base, size); | ||||||
|  |     anal.Analyse(); | ||||||
|  |     anal.SetMarkers(); | ||||||
|  |     GuiUpdateAllViews(); | ||||||
|  |     return STATUS_CONTINUE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| CMDRESULT cbInstrVisualize(int argc, char* argv[]) | CMDRESULT cbInstrVisualize(int argc, char* argv[]) | ||||||
| { | { | ||||||
|     if(argc < 3) |     if(argc < 3) | ||||||
|  | @ -1950,7 +1963,7 @@ CMDRESULT cbInstrVisualize(int argc, char* argv[]) | ||||||
|                     break; |                     break; | ||||||
| 
 | 
 | ||||||
|                 const cs_x86_op & operand = _cp.x86().operands[0]; |                 const cs_x86_op & operand = _cp.x86().operands[0]; | ||||||
|                 if(_cp.InGroup(CS_GRP_JUMP) && operand.type == X86_OP_IMM)    //jump
 |                 if((_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop()) && operand.type == X86_OP_IMM)    //jump
 | ||||||
|                 { |                 { | ||||||
|                     uint dest = (uint)operand.imm; |                     uint dest = (uint)operand.imm; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -70,5 +70,6 @@ CMDRESULT cbInstrCapstone(int argc, char* argv[]); | ||||||
| CMDRESULT cbInstrAnalyse(int argc, char* argv[]); | CMDRESULT cbInstrAnalyse(int argc, char* argv[]); | ||||||
| CMDRESULT cbInstrVisualize(int argc, char* argv[]); | CMDRESULT cbInstrVisualize(int argc, char* argv[]); | ||||||
| CMDRESULT cbInstrMeminfo(int argc, char* argv[]); | CMDRESULT cbInstrMeminfo(int argc, char* argv[]); | ||||||
|  | CMDRESULT cbInstrCfanalyse(int argc, char* argv[]); | ||||||
| 
 | 
 | ||||||
| #endif // _INSTRUCTIONS_H
 | #endif // _INSTRUCTIONS_H
 | ||||||
|  |  | ||||||
|  | @ -312,7 +312,7 @@ void* MemAllocRemote(uint Address, SIZE_T Size, DWORD Protect) | ||||||
|     return VirtualAllocEx(fdProcessInfo->hProcess, (void*)Address, Size, MEM_RESERVE | MEM_COMMIT, Protect); |     return VirtualAllocEx(fdProcessInfo->hProcess, (void*)Address, Size, MEM_RESERVE | MEM_COMMIT, Protect); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MemFreeRemote(uint Address) | bool MemFreeRemote(uint Address) | ||||||
| { | { | ||||||
|     VirtualFreeEx(fdProcessInfo->hProcess, (void*)Address, 0, MEM_RELEASE); |     return !!VirtualFreeEx(fdProcessInfo->hProcess, (void*)Address, 0, MEM_RELEASE); | ||||||
| } | } | ||||||
|  | @ -14,4 +14,4 @@ bool MemPatch(void* BaseAddress, void* Buffer, SIZE_T Size, SIZE_T* NumberOfByte | ||||||
| bool MemIsValidReadPtr(uint Address); | bool MemIsValidReadPtr(uint Address); | ||||||
| bool MemIsCanonicalAddress(uint Address); | bool MemIsCanonicalAddress(uint Address); | ||||||
| void* MemAllocRemote(uint Address, SIZE_T Size, DWORD Protect); | void* MemAllocRemote(uint Address, SIZE_T Size, DWORD Protect); | ||||||
| void MemFreeRemote(uint Address); | bool MemFreeRemote(uint Address); | ||||||
|  | @ -203,6 +203,7 @@ static void registercommands() | ||||||
|     dbgcmdnew("capstone", cbInstrCapstone, true); //disassemble using capstone
 |     dbgcmdnew("capstone", cbInstrCapstone, true); //disassemble using capstone
 | ||||||
|     dbgcmdnew("visualize", cbInstrVisualize, true); //visualize analysis
 |     dbgcmdnew("visualize", cbInstrVisualize, true); //visualize analysis
 | ||||||
|     dbgcmdnew("meminfo", cbInstrMeminfo, true); //command to debug memory map bugs
 |     dbgcmdnew("meminfo", cbInstrMeminfo, true); //command to debug memory map bugs
 | ||||||
|  |     dbgcmdnew("cfanal\1cfanalyse\1cfanalyze", cbInstrCfanalyse, true); //control flow analysis
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool cbCommandProvider(char* cmd, int maxlen) | static bool cbCommandProvider(char* cmd, int maxlen) | ||||||
|  |  | ||||||
|  | @ -32,6 +32,7 @@ | ||||||
|     <ClCompile Include="commandparser.cpp" /> |     <ClCompile Include="commandparser.cpp" /> | ||||||
|     <ClCompile Include="comment.cpp" /> |     <ClCompile Include="comment.cpp" /> | ||||||
|     <ClCompile Include="console.cpp" /> |     <ClCompile Include="console.cpp" /> | ||||||
|  |     <ClCompile Include="controlflowanalysis.cpp" /> | ||||||
|     <ClCompile Include="dbghelp_safe.cpp" /> |     <ClCompile Include="dbghelp_safe.cpp" /> | ||||||
|     <ClCompile Include="debugger.cpp" /> |     <ClCompile Include="debugger.cpp" /> | ||||||
|     <ClCompile Include="debugger_commands.cpp" /> |     <ClCompile Include="debugger_commands.cpp" /> | ||||||
|  | @ -72,12 +73,15 @@ | ||||||
|     <ClCompile Include="_dbgfunctions.cpp" /> |     <ClCompile Include="_dbgfunctions.cpp" /> | ||||||
|     <ClCompile Include="_global.cpp" /> |     <ClCompile Include="_global.cpp" /> | ||||||
|     <ClCompile Include="_plugins.cpp" /> |     <ClCompile Include="_plugins.cpp" /> | ||||||
|  |     <ClCompile Include="_scriptapi_assembler.cpp" /> | ||||||
|     <ClCompile Include="_scriptapi_debug.cpp" /> |     <ClCompile Include="_scriptapi_debug.cpp" /> | ||||||
|     <ClCompile Include="_scriptapi_gui.cpp" /> |     <ClCompile Include="_scriptapi_gui.cpp" /> | ||||||
|  |     <ClCompile Include="_scriptapi_misc.cpp" /> | ||||||
|     <ClCompile Include="_scriptapi_pattern.cpp" /> |     <ClCompile Include="_scriptapi_pattern.cpp" /> | ||||||
|     <ClCompile Include="_scriptapi_memory.cpp" /> |     <ClCompile Include="_scriptapi_memory.cpp" /> | ||||||
|     <ClCompile Include="_scriptapi_module.cpp" /> |     <ClCompile Include="_scriptapi_module.cpp" /> | ||||||
|     <ClCompile Include="_scriptapi_register.cpp" /> |     <ClCompile Include="_scriptapi_register.cpp" /> | ||||||
|  |     <ClCompile Include="_scriptapi_stack.cpp" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClInclude Include="addrinfo.h" /> |     <ClInclude Include="addrinfo.h" /> | ||||||
|  | @ -103,6 +107,7 @@ | ||||||
|     <ClInclude Include="commandparser.h" /> |     <ClInclude Include="commandparser.h" /> | ||||||
|     <ClInclude Include="comment.h" /> |     <ClInclude Include="comment.h" /> | ||||||
|     <ClInclude Include="console.h" /> |     <ClInclude Include="console.h" /> | ||||||
|  |     <ClInclude Include="controlflowanalysis.h" /> | ||||||
|     <ClInclude Include="dbghelp\dbghelp.h" /> |     <ClInclude Include="dbghelp\dbghelp.h" /> | ||||||
|     <ClInclude Include="dbghelp_safe.h" /> |     <ClInclude Include="dbghelp_safe.h" /> | ||||||
|     <ClInclude Include="debugger.h" /> |     <ClInclude Include="debugger.h" /> | ||||||
|  | @ -187,12 +192,15 @@ | ||||||
|     <ClInclude Include="_global.h" /> |     <ClInclude Include="_global.h" /> | ||||||
|     <ClInclude Include="_plugins.h" /> |     <ClInclude Include="_plugins.h" /> | ||||||
|     <ClInclude Include="_plugin_types.h" /> |     <ClInclude Include="_plugin_types.h" /> | ||||||
|  |     <ClInclude Include="_scriptapi_assembler.h" /> | ||||||
|     <ClInclude Include="_scriptapi_debug.h" /> |     <ClInclude Include="_scriptapi_debug.h" /> | ||||||
|     <ClInclude Include="_scriptapi_gui.h" /> |     <ClInclude Include="_scriptapi_gui.h" /> | ||||||
|  |     <ClInclude Include="_scriptapi_misc.h" /> | ||||||
|     <ClInclude Include="_scriptapi_pattern.h" /> |     <ClInclude Include="_scriptapi_pattern.h" /> | ||||||
|     <ClInclude Include="_scriptapi_memory.h" /> |     <ClInclude Include="_scriptapi_memory.h" /> | ||||||
|     <ClInclude Include="_scriptapi_module.h" /> |     <ClInclude Include="_scriptapi_module.h" /> | ||||||
|     <ClInclude Include="_scriptapi_register.h" /> |     <ClInclude Include="_scriptapi_register.h" /> | ||||||
|  |     <ClInclude Include="_scriptapi_stack.h" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <PropertyGroup Label="Globals"> |   <PropertyGroup Label="Globals"> | ||||||
|     <ProjectGuid>{E6548308-401E-3A8A-5819-905DB90522A6}</ProjectGuid> |     <ProjectGuid>{E6548308-401E-3A8A-5819-905DB90522A6}</ProjectGuid> | ||||||
|  |  | ||||||
|  | @ -123,7 +123,7 @@ | ||||||
|   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> |   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | ||||||
|     <ClCompile> |     <ClCompile> | ||||||
|       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> |       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||||
|       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> |       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> | ||||||
|       <WarningLevel>Level3</WarningLevel> |       <WarningLevel>Level3</WarningLevel> | ||||||
|       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> |       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  | @ -160,7 +160,7 @@ | ||||||
|   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> |   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | ||||||
|     <ClCompile> |     <ClCompile> | ||||||
|       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> |       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||||
|       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> |       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> | ||||||
|       <WarningLevel>Level3</WarningLevel> |       <WarningLevel>Level3</WarningLevel> | ||||||
|       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> |       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  |  | ||||||
|  | @ -410,6 +410,27 @@ void Bridge::emitShowCpu() | ||||||
|     emit showCpu(); |     emit showCpu(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Bridge::emitAddQWidgetTab(QWidget* qWidget) | ||||||
|  | { | ||||||
|  |     emit addQWidgetTab(qWidget); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Bridge::emitShowQWidgetTab(QWidget* qWidget) | ||||||
|  | { | ||||||
|  |     emit showQWidgetTab(qWidget); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Bridge::emitCloseQWidgetTab(QWidget* qWidget) | ||||||
|  | { | ||||||
|  |     emit closeQWidgetTab(qWidget); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Bridge::emitExecuteOnGuiThread(void* cbGuiThread) | ||||||
|  | { | ||||||
|  |     GuiAddLogMessage(QString().sprintf("thread id (bridge) %X\n", GetCurrentThreadId()).toUtf8().constData()); | ||||||
|  |     emit executeOnGuiThread(cbGuiThread); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /************************************************************************************
 | /************************************************************************************
 | ||||||
|                             Static Functions |                             Static Functions | ||||||
| ************************************************************************************/ | ************************************************************************************/ | ||||||
|  | @ -824,6 +845,30 @@ __declspec(dllexport) void* _gui_sendmessage(GUIMSG type, void* param1, void* pa | ||||||
|     } |     } | ||||||
|     break; |     break; | ||||||
| 
 | 
 | ||||||
|  |     case GUI_ADD_QWIDGET_TAB: | ||||||
|  |     { | ||||||
|  |         Bridge::getBridge()->emitAddQWidgetTab((QWidget*)param1); | ||||||
|  |     } | ||||||
|  |     break; | ||||||
|  | 
 | ||||||
|  |     case GUI_SHOW_QWIDGET_TAB: | ||||||
|  |     { | ||||||
|  |         Bridge::getBridge()->emitShowQWidgetTab((QWidget*)param1); | ||||||
|  |     } | ||||||
|  |     break; | ||||||
|  | 
 | ||||||
|  |     case GUI_CLOSE_QWIDGET_TAB: | ||||||
|  |     { | ||||||
|  |         Bridge::getBridge()->emitCloseQWidgetTab((QWidget*)param1); | ||||||
|  |     } | ||||||
|  |     break; | ||||||
|  | 
 | ||||||
|  |     case GUI_EXECUTE_ON_GUI_THREAD: | ||||||
|  |     { | ||||||
|  |         Bridge::getBridge()->emitExecuteOnGuiThread(param1); | ||||||
|  |     } | ||||||
|  |     break; | ||||||
|  | 
 | ||||||
|     default: |     default: | ||||||
|     { |     { | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <agents.h> | #include <agents.h> | ||||||
| #include <QObject> | #include <QObject> | ||||||
|  | #include <QWidget> | ||||||
| #include <QMutex> | #include <QMutex> | ||||||
| #include "Imports.h" | #include "Imports.h" | ||||||
| #include "NewTypes.h" | #include "NewTypes.h" | ||||||
|  | @ -87,6 +88,10 @@ public: | ||||||
|     void emitSetMenuEntryIcon(int hEntry, const ICONDATA* icon); |     void emitSetMenuEntryIcon(int hEntry, const ICONDATA* icon); | ||||||
|     void emitSetMenuIcon(int hMenu, const ICONDATA* icon); |     void emitSetMenuIcon(int hMenu, const ICONDATA* icon); | ||||||
|     void emitShowCpu(); |     void emitShowCpu(); | ||||||
|  |     void emitAddQWidgetTab(QWidget* qWidget); | ||||||
|  |     void emitShowQWidgetTab(QWidget* qWidget); | ||||||
|  |     void emitCloseQWidgetTab(QWidget* qWidget); | ||||||
|  |     void emitExecuteOnGuiThread(void* cbGuiThread); | ||||||
| 
 | 
 | ||||||
|     //Public variables
 |     //Public variables
 | ||||||
|     void* winId; |     void* winId; | ||||||
|  | @ -156,6 +161,10 @@ signals: | ||||||
|     void setIconMenuEntry(int hEntry, QIcon icon); |     void setIconMenuEntry(int hEntry, QIcon icon); | ||||||
|     void setIconMenu(int hMenu, QIcon icon); |     void setIconMenu(int hMenu, QIcon icon); | ||||||
|     void showCpu(); |     void showCpu(); | ||||||
|  |     void addQWidgetTab(QWidget* qWidget); | ||||||
|  |     void showQWidgetTab(QWidget* qWidget); | ||||||
|  |     void closeQWidgetTab(QWidget* qWidget); | ||||||
|  |     void executeOnGuiThread(void* cbGuiThread); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     QMutex* mBridgeMutex; |     QMutex* mBridgeMutex; | ||||||
|  |  | ||||||
|  | @ -31,6 +31,10 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi | ||||||
|     connect(Bridge::getBridge(), SIGNAL(setIconMenu(int, QIcon)), this, SLOT(setIconMenu(int, QIcon))); |     connect(Bridge::getBridge(), SIGNAL(setIconMenu(int, QIcon)), this, SLOT(setIconMenu(int, QIcon))); | ||||||
|     connect(Bridge::getBridge(), SIGNAL(setIconMenuEntry(int, QIcon)), this, SLOT(setIconMenuEntry(int, QIcon))); |     connect(Bridge::getBridge(), SIGNAL(setIconMenuEntry(int, QIcon)), this, SLOT(setIconMenuEntry(int, QIcon))); | ||||||
|     connect(Bridge::getBridge(), SIGNAL(showCpu()), this, SLOT(displayCpuWidget())); |     connect(Bridge::getBridge(), SIGNAL(showCpu()), this, SLOT(displayCpuWidget())); | ||||||
|  |     connect(Bridge::getBridge(), SIGNAL(addQWidgetTab(QWidget*)), this, SLOT(addQWidgetTab(QWidget*))); | ||||||
|  |     connect(Bridge::getBridge(), SIGNAL(showQWidgetTab(QWidget*)), this, SLOT(showQWidgetTab(QWidget*))); | ||||||
|  |     connect(Bridge::getBridge(), SIGNAL(closeQWidgetTab(QWidget*)), this, SLOT(closeQWidgetTab(QWidget*))); | ||||||
|  |     connect(Bridge::getBridge(), SIGNAL(executeOnGuiThread(void*)), this, SLOT(executeOnGuiThread(void*))); | ||||||
| 
 | 
 | ||||||
|     //setup menu api
 |     //setup menu api
 | ||||||
|     initMenuApi(); |     initMenuApi(); | ||||||
|  | @ -130,17 +134,17 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi | ||||||
|     mTabWidget = new MHTabWidget(NULL); |     mTabWidget = new MHTabWidget(NULL); | ||||||
| 
 | 
 | ||||||
|     //Setup tabs
 |     //Setup tabs
 | ||||||
|     mTabWidget->addTab(mCpuWidget, mCpuWidget->windowIcon(), mCpuWidget->windowTitle()); |     addQWidgetTab(mCpuWidget); | ||||||
|     mTabWidget->addTab(mLogView, mLogView->windowIcon(), mLogView->windowTitle()); |     addQWidgetTab(mLogView); | ||||||
|     mTabWidget->addTab(mBreakpointsView, mBreakpointsView->windowIcon(), mBreakpointsView->windowTitle()); |     addQWidgetTab(mBreakpointsView); | ||||||
|     mTabWidget->addTab(mMemMapView, mMemMapView->windowIcon(), mMemMapView->windowTitle()); |     addQWidgetTab(mMemMapView); | ||||||
|     mTabWidget->addTab(mCallStackView, mCallStackView->windowIcon(), mCallStackView->windowTitle()); |     addQWidgetTab(mCallStackView); | ||||||
|     mTabWidget->addTab(mScriptView, mScriptView->windowIcon(), mScriptView->windowTitle()); |     addQWidgetTab(mScriptView); | ||||||
|     mTabWidget->addTab(mSymbolView, mSymbolView->windowIcon(), mSymbolView->windowTitle()); |     addQWidgetTab(mSymbolView); | ||||||
|     mTabWidget->addTab(mSourceViewManager, mSourceViewManager->windowIcon(), mSourceViewManager->windowTitle()); |     addQWidgetTab(mSourceViewManager); | ||||||
|     mTabWidget->addTab(mReferenceManager, mReferenceManager->windowIcon(), mReferenceManager->windowTitle()); |     addQWidgetTab(mReferenceManager); | ||||||
|     mTabWidget->addTab(mThreadView, mThreadView->windowIcon(), mThreadView->windowTitle()); |     addQWidgetTab(mThreadView); | ||||||
|     mTabWidget->addTab(mSnowmanView, mSnowmanView->windowIcon(), mSnowmanView->windowTitle()); |     addQWidgetTab(mSnowmanView); | ||||||
| 
 | 
 | ||||||
|     setCentralWidget(mTabWidget); |     setCentralWidget(mTabWidget); | ||||||
| 
 | 
 | ||||||
|  | @ -237,6 +241,8 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi | ||||||
|     mCloseDialog = new CloseDialog(this); |     mCloseDialog = new CloseDialog(this); | ||||||
| 
 | 
 | ||||||
|     mCpuWidget->mDisas->setFocus(); |     mCpuWidget->mDisas->setFocus(); | ||||||
|  | 
 | ||||||
|  |     GuiAddLogMessage(QString().sprintf("thread id (GUI thread) %X\n", GetCurrentThreadId()).toUtf8().constData()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindow::closeEvent(QCloseEvent* event) | void MainWindow::closeEvent(QCloseEvent* event) | ||||||
|  | @ -343,7 +349,7 @@ void MainWindow::loadMRUList(int maxItems) | ||||||
|     mMaxMRU = maxItems; |     mMaxMRU = maxItems; | ||||||
|     for(int i = 0; i < mMaxMRU; i++) |     for(int i = 0; i < mMaxMRU; i++) | ||||||
|     { |     { | ||||||
|         char currentFile[MAX_PATH] = ""; |         char currentFile[MAX_SETTING_SIZE] = ""; | ||||||
|         if(!BridgeSettingGet("Recent Files", QString().sprintf("%.2d", i + 1).toUtf8().constData(), currentFile)) |         if(!BridgeSettingGet("Recent Files", QString().sprintf("%.2d", i + 1).toUtf8().constData(), currentFile)) | ||||||
|             break; |             break; | ||||||
|         if(QString(currentFile).size() && QFile(currentFile).exists()) |         if(QString(currentFile).size() && QFile(currentFile).exists()) | ||||||
|  | @ -488,23 +494,17 @@ void MainWindow::execRtr() | ||||||
| 
 | 
 | ||||||
| void MainWindow::displayMemMapWidget() | void MainWindow::displayMemMapWidget() | ||||||
| { | { | ||||||
|     mMemMapView->show(); |     showQWidgetTab(mMemMapView); | ||||||
|     mMemMapView->setFocus(); |  | ||||||
|     setTab(mMemMapView); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindow::displayLogWidget() | void MainWindow::displayLogWidget() | ||||||
| { | { | ||||||
|     mLogView->show(); |     showQWidgetTab(mLogView); | ||||||
|     mLogView->setFocus(); |  | ||||||
|     setTab(mLogView); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindow::displayScriptWidget() | void MainWindow::displayScriptWidget() | ||||||
| { | { | ||||||
|     mScriptView->show(); |     showQWidgetTab(mScriptView); | ||||||
|     mScriptView->setFocus(); |  | ||||||
|     setTab(mScriptView); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindow::displayAboutWidget() | void MainWindow::displayAboutWidget() | ||||||
|  | @ -607,9 +607,7 @@ void MainWindow::restartDebugging() | ||||||
| 
 | 
 | ||||||
| void MainWindow::displayBreakpointWidget() | void MainWindow::displayBreakpointWidget() | ||||||
| { | { | ||||||
|     mBreakpointsView->show(); |     showQWidgetTab(mBreakpointsView); | ||||||
|     mBreakpointsView->setFocus(); |  | ||||||
|     setTab(mBreakpointsView); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindow::dragEnterEvent(QDragEnterEvent* pEvent) | void MainWindow::dragEnterEvent(QDragEnterEvent* pEvent) | ||||||
|  | @ -667,44 +665,32 @@ void MainWindow::execSkip() | ||||||
| 
 | 
 | ||||||
| void MainWindow::displayCpuWidget() | void MainWindow::displayCpuWidget() | ||||||
| { | { | ||||||
|     mCpuWidget->show(); |     showQWidgetTab(mCpuWidget); | ||||||
|     mCpuWidget->setFocus(); |  | ||||||
|     setTab(mCpuWidget); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindow::displaySymbolWidget() | void MainWindow::displaySymbolWidget() | ||||||
| { | { | ||||||
|     mSymbolView->show(); |     showQWidgetTab(mSymbolView); | ||||||
|     mSymbolView->setFocus(); |  | ||||||
|     setTab(mSymbolView); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindow::displaySourceViewWidget() | void MainWindow::displaySourceViewWidget() | ||||||
| { | { | ||||||
|     mSourceViewManager->show(); |     showQWidgetTab(mSourceViewManager); | ||||||
|     mSourceViewManager->setFocus(); |  | ||||||
|     setTab(mSourceViewManager); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindow::displayReferencesWidget() | void MainWindow::displayReferencesWidget() | ||||||
| { | { | ||||||
|     mReferenceManager->show(); |     showQWidgetTab(mReferenceManager); | ||||||
|     mReferenceManager->setFocus(); |  | ||||||
|     setTab(mReferenceManager); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindow::displayThreadsWidget() | void MainWindow::displayThreadsWidget() | ||||||
| { | { | ||||||
|     mThreadView->show(); |     showQWidgetTab(mThreadView); | ||||||
|     mThreadView->setFocus(); |  | ||||||
|     setTab(mThreadView); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindow::displaySnowmanWidget() | void MainWindow::displaySnowmanWidget() | ||||||
| { | { | ||||||
|     mSnowmanView->show(); |     showQWidgetTab(mSnowmanView); | ||||||
|     mSnowmanView->setFocus(); |  | ||||||
|     setTab(mSnowmanView); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindow::openSettings() | void MainWindow::openSettings() | ||||||
|  | @ -1025,9 +1011,7 @@ void MainWindow::checkUpdates() | ||||||
| 
 | 
 | ||||||
| void MainWindow::displayCallstack() | void MainWindow::displayCallstack() | ||||||
| { | { | ||||||
|     mCallStackView->show(); |     showQWidgetTab(mCallStackView); | ||||||
|     mCallStackView->setFocus(); |  | ||||||
|     setTab(mCallStackView); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindow::donate() | void MainWindow::donate() | ||||||
|  | @ -1122,3 +1106,30 @@ void MainWindow::canClose() | ||||||
|     bCanClose = true; |     bCanClose = true; | ||||||
|     close(); |     close(); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void MainWindow::addQWidgetTab(QWidget* qWidget) | ||||||
|  | { | ||||||
|  |     mTabWidget->addTab(qWidget, qWidget->windowIcon(), qWidget->windowTitle()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MainWindow::showQWidgetTab(QWidget* qWidget) | ||||||
|  | { | ||||||
|  |     qWidget->show(); | ||||||
|  |     qWidget->setFocus(); | ||||||
|  |     setTab(qWidget); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MainWindow::closeQWidgetTab(QWidget* qWidget) | ||||||
|  | { | ||||||
|  |     for(int i = 0; i < mTabWidget->count(); i++) | ||||||
|  |         if(mTabWidget->widget(i) == qWidget) | ||||||
|  |         { | ||||||
|  |             mTabWidget->DeleteTab(i); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MainWindow::executeOnGuiThread(void* cbGuiThread) | ||||||
|  | { | ||||||
|  |     ((GUICALLBACK)cbGuiThread)(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -104,6 +104,10 @@ public slots: | ||||||
|     void changeCommandLine(); |     void changeCommandLine(); | ||||||
|     void decompileAt(int_t start, int_t end); |     void decompileAt(int_t start, int_t end); | ||||||
|     void canClose(); |     void canClose(); | ||||||
|  |     void addQWidgetTab(QWidget* qWidget); | ||||||
|  |     void showQWidgetTab(QWidget* qWidget); | ||||||
|  |     void closeQWidgetTab(QWidget* qWidget); | ||||||
|  |     void executeOnGuiThread(void* cbGuiThread); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Ui::MainWindow* ui; |     Ui::MainWindow* ui; | ||||||
|  |  | ||||||
|  | @ -579,7 +579,7 @@ void ScriptView::cmdExec() | ||||||
| 
 | 
 | ||||||
| void ScriptView::message(QString message) | void ScriptView::message(QString message) | ||||||
| { | { | ||||||
|     QMessageBox msg(QMessageBox::Information, "Information", message); |     QMessageBox msg(QMessageBox::Information, "Message", message); | ||||||
|     msg.setWindowIcon(QIcon(":/icons/images/information.png")); |     msg.setWindowIcon(QIcon(":/icons/images/information.png")); | ||||||
|     msg.setParent(this, Qt::Dialog); |     msg.setParent(this, Qt::Dialog); | ||||||
|     msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); |     msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); | ||||||
|  |  | ||||||
|  | @ -80,7 +80,7 @@ | ||||||
|   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> |   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | ||||||
|     <ClCompile> |     <ClCompile> | ||||||
|       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> |       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||||
|       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> |       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> | ||||||
|       <WarningLevel>Level3</WarningLevel> |       <WarningLevel>Level3</WarningLevel> | ||||||
|       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> |       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue