├── Debugger
├── SymbolEngine.cpp
├── Res
│ ├── Debugger.rc
│ ├── resource.h
│ └── Debugger.aps
├── Dasm
│ ├── DasmEngine.cpp
│ ├── Dasm.h
│ ├── Utils.h
│ ├── DasmInc.h
│ ├── Utils.cpp
│ └── Dasm.cpp
├── Debugger.vcxproj.user
├── Inc
│ ├── SymbolEngine.h
│ ├── DebuggerDP.h
│ ├── CustomErrors.h
│ ├── MenuItems.h
│ ├── Debug.h
│ ├── Assert.h
│ ├── WndProc.h
│ ├── Common.h
│ ├── StringLengths.h
│ ├── UICommon.h
│ ├── UICreator.h
│ ├── SourceHelpers.h
│ ├── GuiManager.h
│ ├── Logger.h
│ ├── GuiDebugCommon.h
│ ├── CustomEvents.h
│ ├── Breakpoint.h
│ ├── DebugHelpers.h
│ └── DebugCommon.h
├── Lib
│ └── include
│ │ ├── StringFunctions.h
│ │ ├── Helpers.h
│ │ ├── CommonInclude.h
│ │ ├── IOFunctions.h
│ │ ├── MemFunctions.h
│ │ ├── General.h
│ │ ├── DbgHelpers.h
│ │ ├── ProcessFunctions.h
│ │ ├── GuiFunctions.h
│ │ ├── Assert.h
│ │ ├── InternalDefines.h
│ │ ├── Queue.h
│ │ ├── Defines.h
│ │ ├── LinkedList.h
│ │ ├── Stack.h
│ │ ├── RArray.h
│ │ ├── Hashtable.h
│ │ └── BinarySearchTree.h
├── Assert.cpp
├── DebuggerDP.cpp
├── MenuItems.cpp
├── WinMain.cpp
├── Logger.cpp
├── Debugger.vcxproj.filters
├── Debugger.vcxproj
├── Breakpoint.cpp
├── UICreator.cpp
├── WndProc.cpp
└── GuiManager.cpp
├── README
├── Debugger.sln
└── .gitignore
/Debugger/SymbolEngine.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Inc\SymbolEngine.h"
--------------------------------------------------------------------------------
/Debugger/Res/Debugger.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishir993/debugger/HEAD/Debugger/Res/Debugger.rc
--------------------------------------------------------------------------------
/Debugger/Res/resource.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishir993/debugger/HEAD/Debugger/Res/resource.h
--------------------------------------------------------------------------------
/Debugger/Res/Debugger.aps:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishir993/debugger/HEAD/Debugger/Res/Debugger.aps
--------------------------------------------------------------------------------
/Debugger/Dasm/DasmEngine.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishir993/debugger/HEAD/Debugger/Dasm/DasmEngine.cpp
--------------------------------------------------------------------------------
/Debugger/Debugger.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Debugger/Inc/SymbolEngine.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _SYMBOLENGINE_H
3 | #define _SYMBOLENGINE_H
4 |
5 | #include
6 | #include
7 |
8 |
9 |
10 | #endif // _SYMBOLENGINE_H
11 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | ** Second try at writing full fledged debugger**
2 |
3 | - This is a debugger that works with Windows 32bit PE files.
4 | - Written in C using plain old Win32 APIs
5 | - It is being developed as a debugger with its own GUI
--------------------------------------------------------------------------------
/Debugger/Inc/DebuggerDP.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _DEBUGGERDP_H
3 | #define _DEBUGGERDP_H
4 |
5 | #include "Common.h"
6 | #include "UICommon.h"
7 |
8 | BOOL CALLBACK DebuggerDP(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
9 |
10 | #endif // _DEBUGGERDP_H
11 |
--------------------------------------------------------------------------------
/Debugger/Inc/CustomErrors.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _CUSTOMERRORS_H
3 | #define _CUSTOMERRORS_H
4 |
5 | #define CE_WMAIN_ERROR 1
6 | #define CE_WNDPROC_INIT 2
7 | #define CE_DIALOG_ERROR_RETURN 3
8 |
9 | #define CE_ASSERT_FAILED 0x666
10 |
11 | #endif // _CUSTOMERRORS_H
12 |
--------------------------------------------------------------------------------
/Debugger/Inc/MenuItems.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _MENUITEMS_H
3 | #define _MENUITEMS_H
4 |
5 | #include "Common.h"
6 |
7 | // Functions
8 | void vMiDebuggerInit(HMENU hMenu);
9 | void vMiDebugSessionStart(HMENU hMenu);
10 | void vMiDebugSessionEnd(HMENU hMenu);
11 | void vMiDebuggerRunning(HMENU hMenu);
12 | void vMiDebuggerDebugging(HMENU hMenu);
13 |
14 | #endif // _MENUITEMS_H
15 |
--------------------------------------------------------------------------------
/Debugger/Inc/Debug.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _DEBUG_H
3 | #define _DEBUG_H
4 |
5 | #include "Common.h"
6 | #include "UICreator.h"
7 | #include "Defines.h"
8 | #include "Breakpoint.h"
9 | #include "DebugCommon.h"
10 |
11 | #define EXITCODE_TARGET_TERM 0xDEAD
12 |
13 | // **** Functions ****
14 | DWORD WINAPI dwDebugThreadEntry(LPVOID lpvArgs);
15 |
16 |
17 | #endif // _DEBUG_H
18 |
--------------------------------------------------------------------------------
/Debugger/Inc/Assert.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _ASSERT_H
3 | #define _ASSERT_H
4 |
5 | #include
6 | #include
7 | #include
8 | #include "StringLengths.h"
9 | #include "CustomErrors.h"
10 |
11 | #ifdef _DEBUG
12 | void vAssert(const char* psFile, UINT uLine);
13 | #define ASSERT(x) \
14 | if(x) {} \
15 | else \
16 | vAssert(__FILE__, __LINE__)
17 | #else
18 | #define ASSERT(x)
19 | #endif
20 |
21 | #endif //_ASSERT_H
22 |
--------------------------------------------------------------------------------
/Debugger/Dasm/Dasm.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _DASM_H
3 | #define _DASM_H
4 |
5 | #include "DasmInc.h"
6 | #include "DasmEngine.h"
7 | #include "Utils.h"
8 |
9 | #define EXEFILEMAP_NAME L"InputFileMapName"
10 |
11 | int wmain(int argc, WCHAR **argv);
12 | BOOL fCmdArgsHandler(int argc, WCHAR **argv, WCHAR *pwszInFile,
13 | DWORD dwInFileBufSize);
14 | void vRunTests();
15 | BOOL fCloseFile(HANDLE hFile, HANDLE hFileMapObj,
16 | HANDLE hFileView);
17 |
18 | #endif // _DASM_H
--------------------------------------------------------------------------------
/Debugger/Inc/WndProc.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _WNDPROC_H
3 | #define _WNDPROC_H
4 |
5 | #include "Common.h"
6 |
7 | #include
8 | #include
9 |
10 | #include "UICommon.h"
11 | #include "Logger.h"
12 | #include "UICreator.h"
13 | #include "Defines.h"
14 |
15 | typedef struct _DbgSessionStart {
16 | BOOL fDebuggingActiveProcess;
17 | BOOL fBreakAtMain;
18 | DWORD dwTargetPID;
19 | WCHAR szTargetPath[SLEN_MAXPATH];
20 | }DBG_SESSIONSTART, *PDBG_SESSIONSTART;
21 |
22 | LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
23 |
24 | #endif // _WNDPROC_H
25 |
--------------------------------------------------------------------------------
/Debugger/Inc/Common.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _COMMON_H
3 | #define _COMMON_H
4 |
5 | #include
6 | #include
7 | #include
8 |
9 | #include "Assert.h"
10 | #include "CustomErrors.h"
11 | #include "StringLengths.h"
12 | #include "SourceHelpers.h"
13 | #include "Logger.h"
14 | #include "CustomEvents.h"
15 |
16 | // ** CHelpLib includes **
17 |
18 | #include "GuiFunctions.h"
19 | #include "MemFunctions.h"
20 | #include "LinkedList.h"
21 | #include "Hashtable.h"
22 | #include "ProcessFunctions.h"
23 | #include "StringFunctions.h"
24 | #include "General.h"
25 |
26 | #endif // _COMMON_H
27 |
--------------------------------------------------------------------------------
/Debugger/Inc/StringLengths.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _STRINGLENGTHS_H
3 | #define _STRINGLENGTHS_H
4 |
5 | #define SLEN_COMMON16 16
6 | #define SLEN_COMMON32 32
7 | #define SLEN_COMMON64 64
8 | #define SLEN_COMMON128 128
9 | #define SLEN_INT16 8
10 | #define SLEN_INT32 16
11 | #define SLEN_LOGLINE 1024
12 | #define SLEN_MAXPATH 1024
13 |
14 | #define SLEN_EVENTNAMES SLEN_COMMON32
15 | #define SLEN_EXCEPTION_NAME SLEN_COMMON128
16 |
17 | #define SLEN_DWORDSTR_HEX 16 // DWORD value represented in hex with leading 0x
18 |
19 | #define SLEN_REGISTER_NAME 8
20 |
21 | #endif // _STRINGLENGTHS_H
22 |
--------------------------------------------------------------------------------
/Debugger/Inc/UICommon.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _UICOMMON_H
3 | #define _UICOMMON_H
4 |
5 | #include
6 |
7 | #include "..\Res\resource.h"
8 |
9 | // IDs for controls created on the fly
10 | #define IDC_MAINTAB 6601
11 | //#define IDC_EDIT_DISASS 6602
12 | //#define IDC_LIST_CALLSTACK 6603
13 | //#define IDC_LIST_REGISTERS 6604
14 | //#define IDC_LIST_THREADS 6605
15 | //#define IDC_TAB_BOTTOM 6606
16 | //#define IDC_EDIT_COMMAND 6607
17 |
18 | // UI
19 | #define PADDING_LONE 6
20 | #define PADDING_TOGETHER 3
21 |
22 | // UI Class names
23 | #define CNAME_EDIT L"EDIT"
24 | #define CNAME_LIST L"LISTBOX"
25 | #define CNAME_STATIC L"STATIC"
26 |
27 |
28 | #endif
29 |
--------------------------------------------------------------------------------
/Debugger/Lib/include/StringFunctions.h:
--------------------------------------------------------------------------------
1 | // StringFunctions.h
2 | // Contains functions that provide string operations
3 | // Shishir Bhat (http://www.shishirbhat.com)
4 | // History
5 | // 08/10/13 Initial version
6 | // 09/09/14 Refactor to store defs in individual headers.
7 | //
8 |
9 | #ifndef _STRINGFUNCTIONS_H
10 | #define _STRINGFUNCTIONS_H
11 |
12 | #ifdef __cplusplus
13 | extern "C" {
14 | #endif
15 |
16 | #include "Defines.h"
17 |
18 | // -------------------------------------------
19 | // Functions exported
20 |
21 | DllExpImp PCWSTR CHL_SzGetFilenameFromPath(_In_z_ PCWSTR pszFilepath, _In_ int numCharsInput);
22 |
23 | #ifdef __cplusplus
24 | }
25 | #endif
26 |
27 | #endif // _STRINGFUNCTIONS_H
28 |
--------------------------------------------------------------------------------
/Debugger/Lib/include/Helpers.h:
--------------------------------------------------------------------------------
1 |
2 | // Helpers.h
3 | // Contains handy helper defines and functions
4 | // Shishir Bhat (http://www.shishirbhat.com)
5 | // History
6 | // 06/23/13 Initial version
7 | //
8 |
9 | #ifndef _HELPERS_H
10 | #define _HELPERS_H
11 |
12 | #ifdef __cplusplus
13 | extern "C" {
14 | #endif
15 |
16 | // Pass a pointer and value to this, assignment takes place only if
17 | // the pointer is not NULL
18 | #define IFPTR_SETVAL(ptr, val) { if(ptr) *ptr = val; }
19 |
20 | #define IFPTR_FREE(ptr) if(ptr) { CHL_MmFree((void**)&ptr); }
21 |
22 | #define ISVALID_HANDLE(handle) (handle != NULL && handle != INVALID_HANDLE_VALUE)
23 |
24 | #ifdef __cplusplus
25 | }
26 | #endif
27 |
28 | #endif // _HELPERS_H
29 |
--------------------------------------------------------------------------------
/Debugger/Lib/include/CommonInclude.h:
--------------------------------------------------------------------------------
1 |
2 | // CommonInclude.h
3 | // Contains common includes, defs and typedefs
4 | // Shishir Bhat (http://www.shishirbhat.com)
5 | // History
6 | // 06/23/13 Initial version
7 | // 09/18/2014 Standardize keys and value types
8 | // 08/04/2015 Make individual headers usable by clients
9 | //
10 |
11 | #ifndef _COMMONINCLUDE_H
12 | #define _COMMONINCLUDE_H
13 |
14 | #ifdef __cplusplus
15 | extern "C" {
16 | #endif
17 |
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | #ifdef __cplusplus
28 | }
29 | #endif
30 |
31 | #endif // _COMMONINCLUDE_H
32 |
--------------------------------------------------------------------------------
/Debugger/Assert.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Inc\Assert.h"
3 |
4 | void vAssert(const char* pszFile, UINT uLine)
5 | {
6 | // ensure that all buffers are written out first
7 | fflush(NULL);
8 | fprintf(stderr, "Assertion failed in %s at Line %u\n", pszFile, uLine);
9 | fflush(stderr);
10 |
11 | // Adding a hard breakpoint because:
12 | // In GUI programs, there is usually no console window open to display the assertion failure.
13 | // Even when a GUI program explicitly opens a console window, exiting the program causes
14 | // the console also to be closed immediately. So we cannot see where the assertion failed.
15 |
16 | if(IsDebuggerPresent())
17 | {
18 | fprintf(stderr, "Debugger is present. Causing a breakpoint exception.\n");
19 | __asm int 3
20 | }
21 |
22 | exit(CE_ASSERT_FAILED);
23 | }
24 |
--------------------------------------------------------------------------------
/Debugger/Inc/UICreator.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _UICREATOR_H
3 | #define _UICREATOR_H
4 |
5 | #include "Common.h"
6 | #include "UICommon.h"
7 |
8 | typedef struct _TabPageInfo {
9 | int iTabIndex;
10 | HWND hMainTab;
11 | HWND hEditDisass;
12 | HWND hTabBottom;
13 | HWND hListCallStack;
14 | HWND hListRegisters;
15 | HWND hListThreads;
16 | HWND hEditCommand;
17 | HWND hStaticCommand;
18 |
19 | HFONT hFixedFont;
20 | }TABPAGEINFO, *PTABPAGEINFO;
21 |
22 | BOOL fCreateMainTabControl(HWND hMainWnd, __out HWND *phTabControl, __out DWORD *pdwErrCode);
23 | BOOL fCreateTabPage(HWND hTab, __out PTABPAGEINFO pstTabPageInfo, __out DWORD *pdwErrCode);
24 | void vDeleteTabPage(HWND hTab, PTABPAGEINFO pstTabPageInfo);
25 | BOOL fSetTabPageText(HWND hTab, int iTabIndex, PCWSTR pszTabText);
26 |
27 | #endif // _UICREATOR_H
28 |
--------------------------------------------------------------------------------
/Debugger/Lib/include/IOFunctions.h:
--------------------------------------------------------------------------------
1 |
2 | // IOFunctions.h
3 | // Contains functions that provide IO operation services
4 | // Shishir Bhat (http://www.shishirbhat.com)
5 | // History
6 | // 06/23/13 Initial version
7 | // 09/09/14 Refactor to store defs in individual headers.
8 | // 09/12/14 Naming convention modifications
9 | //
10 |
11 | #ifndef _IOFUNCTIONS_H
12 | #define _IOFUNCTIONS_H
13 |
14 | #ifdef __cplusplus
15 | extern "C" {
16 | #endif
17 |
18 | #include "Defines.h"
19 | #include "MemFunctions.h"
20 |
21 | // -------------------------------------------
22 | // Functions exported
23 |
24 | DllExpImp HRESULT CHL_IoReadLineFromStdin(_Inout_z_bytecap_x_(dwBufSize) PWSTR pszBuffer, _In_ DWORD dwBufSize);
25 | DllExpImp HRESULT CHL_IoCreateFileWithSize(_Out_ PHANDLE phFile, _In_z_ PWCHAR pszFilepath, _In_ int iSizeBytes);
26 |
27 |
28 | #ifdef __cplusplus
29 | }
30 | #endif
31 |
32 | #endif // _IOFUNCTIONS_H
33 |
--------------------------------------------------------------------------------
/Debugger.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 11.00
3 | # Visual Studio 2010
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Debugger", "Debugger\Debugger.vcxproj", "{EDEFC84A-1AD6-4FA6-8042-E198F3172866}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Win32 = Debug|Win32
9 | Release|Win32 = Release|Win32
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {EDEFC84A-1AD6-4FA6-8042-E198F3172866}.Debug|Win32.ActiveCfg = Debug|Win32
13 | {EDEFC84A-1AD6-4FA6-8042-E198F3172866}.Debug|Win32.Build.0 = Debug|Win32
14 | {EDEFC84A-1AD6-4FA6-8042-E198F3172866}.Release|Win32.ActiveCfg = Release|Win32
15 | {EDEFC84A-1AD6-4FA6-8042-E198F3172866}.Release|Win32.Build.0 = Release|Win32
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/Debugger/Lib/include/MemFunctions.h:
--------------------------------------------------------------------------------
1 |
2 | // MemFunctions.h
3 | // Contains functions that provide memory alloc/dealloc services
4 | // Shishir Bhat (http://www.shishirbhat.com)
5 | // History
6 | // 06/23/13 Initial version
7 | // 09/09/14 Refactor to store defs in individual headers.
8 | // 09/12/14 Naming convention modifications
9 | //
10 |
11 | #ifndef _MEMFUNCTIONS_H
12 | #define _MEMFUNCTIONS_H
13 |
14 | #ifdef __cplusplus
15 | extern "C" {
16 | #endif
17 |
18 | #include "Defines.h"
19 |
20 | // Custom error codes
21 | #define CHLE_MEM_ENOMEM 17000
22 | #define CHLE_MEM_GEN 17001
23 |
24 | // -------------------------------------------
25 | // Functions exported
26 |
27 | DllExpImp HRESULT CHL_MmAlloc(_Out_cap_(uSizeBytes) PVOID *ppvAddr, _In_ size_t uSizeBytes, _In_opt_ PDWORD pdwError);
28 | DllExpImp void CHL_MmFree(_In_ PVOID *ppvToFree);
29 |
30 | #ifdef __cplusplus
31 | }
32 | #endif
33 |
34 | #endif // _MEMFUNCTIONS_H
35 |
--------------------------------------------------------------------------------
/Debugger/Dasm/Utils.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _UTILS_H
3 | #define _UTILS_H
4 |
5 | #include
6 | #include "DasmInc.h"
7 | #include "DASMEngine.h"
8 |
9 | #define MOD_MASK 0xC0 // 1100 0000
10 | #define REG_MASK 0x38 // 0011 1000
11 | #define RM_MASK 0x07 // 0000 0111
12 | #define DBIT_MASK 0x02 // 0000 0010
13 | #define WBIT_MASK 0x01 // 0000 0001
14 |
15 | /*
16 | * Utility functions provided
17 | */
18 |
19 | // Instruction utils
20 | void Util_vSplitModRMByte(BYTE bModRMValue, __out PBYTE pbMod,
21 | __out PBYTE pbReg, __out PBYTE pbRM);
22 | void Util_vGetDWBits(BYTE bOpcode, __out PBYTE pbDBit, __out PBYTE pbWBit);
23 | BOOL Util_fIsPrefix(BYTE bValue);
24 |
25 | // PE header related utils
26 | BOOL Util_fDumpIMAGE_IMPORT_DESCRIPTORS(DWORD rva, DWORD dwSize,
27 | PIMAGE_NT_HEADERS pNTHeaders, DWORD dwFileBase);
28 |
29 | // Other
30 | void Util_vTwosComplementByte(BYTE chSignedVal, __out PBYTE pchOut);
31 | void Util_vTwosComplementInt(INT iSignedVal, __out PINT piOut);
32 |
33 |
34 | #endif // _UTILS_H
35 |
--------------------------------------------------------------------------------
/Debugger/Lib/include/General.h:
--------------------------------------------------------------------------------
1 |
2 | // General.h
3 | // Contains general helper functions
4 | // Shishir Bhat (http://www.shishirbhat.com)
5 | // History
6 | // 01/20/14 Initial version
7 | // 09/12/14 Naming convention modifications
8 | //
9 |
10 | #ifndef _GENERAL_H
11 | #define _GENERAL_H
12 |
13 | #ifdef __cplusplus
14 | extern "C" {
15 | #endif
16 |
17 | #include "Defines.h"
18 |
19 | // -------------------------------------------
20 | // Functions exported
21 |
22 | #if !defined(_WIN64)
23 |
24 | DllExpImp BOOL CHL_GnIsOverflowINT(_In_ int a, _In_ int b);
25 | DllExpImp BOOL CHL_GnIsOverflowUINT(_In_ UINT a, _In_ UINT b);
26 |
27 | #endif // _WIN64
28 |
29 | DllExpImp HRESULT CHL_GnCreateMemMapOfFile(
30 | _In_ HANDLE hFile,
31 | _In_ DWORD dwReqProtection,
32 | _Out_ PHANDLE phMapObj,
33 | _Out_ PHANDLE phMapView);
34 |
35 | // -------------------------------------------
36 | // Functions used only within this library
37 |
38 | HRESULT CHL_GnOwnMutex(_In_ HANDLE hMutex);
39 |
40 | #ifdef __cplusplus
41 | }
42 | #endif
43 |
44 | #endif // _GENERAL_H
45 |
--------------------------------------------------------------------------------
/Debugger/Inc/SourceHelpers.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _CODECHECKERS_H
3 | #define _CODECHECKERS_H
4 |
5 | #include
6 |
7 | #define NELEMS_ARRAY(arr_var) (sizeof(arr_var)/sizeof(arr_var[0]))
8 |
9 | #define ISNULL(PtrHandle) (PtrHandle == NULL)
10 | #define ISNULL_GOTO(PtrHandle, gotoLocation) if(ISNULL(PtrHandle)) { goto gotoLocation; }
11 | #define ISVALID_HANDLE(handle) (handle != NULL && handle != INVALID_HANDLE_VALUE)
12 |
13 | #define IFPTR_FREE(ptr) if(!ISNULL(ptr)) { CHL_MmFree((void**)&ptr); }
14 | #define FREE_HANDLE(handle) if(ISVALID_HANDLE(handle)) { CloseHandle(handle); } handle = NULL
15 |
16 | #define IFPTR_SETVAL(ptr, val) if(ptr) { *ptr = val; }
17 | #define SET_ERRORCODE(dwErrCode) { dwErrCode = GetLastError(); }
18 | #define SET_ERRORCODE_PTR(pdwErrCode) { if(!ISNULL(pdwErrCode)) { *pdwErrCode = GetLastError(); } }
19 |
20 | #define CONV_WCHARSIZE(bytes) (bytes * sizeof(WCHAR))
21 | #define CONV_BYTES_wcsnlen_s(wstring, maxcount) ( (wcsnlen_s(wstring, maxcount) + 1) * sizeof(WCHAR) )
22 |
23 | #endif // _CODECHECKERS_H
24 |
--------------------------------------------------------------------------------
/Debugger/Inc/GuiManager.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _GUIMANAGER_H
3 | #define _GUIMANAGER_H
4 |
5 | #include "Common.h"
6 | #include
7 |
8 | #include "UICommon.h"
9 | #include "Defines.h"
10 | #include "GuiDebugCommon.h"
11 |
12 | #define CLEAR_EDITCONTROL(hEditControl) SendMessage(hEditControl, EM_SETSEL, 0, -1); SendMessage(hEditControl, EM_REPLACESEL, FALSE, (LPARAM)L"")
13 |
14 | BOOL fGuiInitialize(__out DWORD *pdwErrCode);
15 | void vGuiExit();
16 | BOOL fGuiAddTab(int tabIndex, DWORD threadId, __out DWORD *pdwErrCode);
17 | BOOL fGuiRemTab(int tabIndex, __out DWORD *pdwErrCode);
18 | BOOL fGuiFindTab(int tabIndex, __out DWORD *pdwThreadId, __out DWORD *pdwErrCode);
19 | BOOL fOnExitDetachTargets();
20 |
21 | BOOL fGuiGetOpenFilename(HWND hMainWindow, WCHAR *pszFilters, __out WCHAR *pszFilepath, DWORD dwBufSize, __out DWORD *pdwErrCode);
22 |
23 | BOOL CALLBACK fGetProcIdDP(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
24 | BOOL CALLBACK fGetNewProgramDP(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
25 |
26 | BOOL fGuiUpdateThreadsList(HWND hThreadListView, PLV_THREADINFO pstLvThreadInfo, int nItems);
27 | BOOL fGuiUpdateRegistersList(HWND hRegsListView, WCHAR *apszNames[], DWORD *padwValues, int nItems);
28 |
29 | #endif // _GUIMANAGER_H
30 |
--------------------------------------------------------------------------------
/Debugger/Inc/Logger.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _LOGGER_H
3 | #define _LOGGER_H
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #include "Assert.h"
11 | #include "StringLengths.h"
12 | #include "..\Res\resource.h"
13 |
14 | #define LOGTYPE_TRACE 0
15 | #define LOGTYPE_WARN 1
16 | #define LOGTYPE_ERROR 2
17 |
18 | #define logtrace(plogger, fmt, ...) vWriteLogType(LOGTYPE_TRACE, plogger, fmt, __VA_ARGS__)
19 | #define logwarn(plogger, fmt, ...) vWriteLogType(LOGTYPE_WARN, plogger, fmt, __VA_ARGS__)
20 | #define logerror(plogger, fmt, ...) vWriteLogType(LOGTYPE_ERROR, plogger, fmt, __VA_ARGS__)
21 |
22 | #ifdef _DEBUG
23 | #define dbgwprintf(fmt, ...) wprintf(fmt, __VA_ARGS__)
24 | #else
25 | #define dbgwprintf(fmt, ...)
26 | #endif
27 |
28 | typedef struct _Logger
29 | {
30 | HANDLE hMutex;
31 | HANDLE hLogFile;
32 | WCHAR szMutexName[SLEN_COMMON64];
33 | }LOGGER, *PLOGGER;
34 |
35 | BOOL fInitializeLogger(WCHAR *pszLogFilepath, __out LOGGER *pLogger);
36 | void vTerminateLogger(LOGGER *pLogger);
37 | void vWriteLog(LOGGER *pLogger, const WCHAR* pszMessageFmt, ...);
38 | void vWriteLogType(int iLogLevel, PLOGGER pLogger, const WCHAR *pszMessageFmt, ...);
39 |
40 | #endif // _LOGGER_H
41 |
--------------------------------------------------------------------------------
/Debugger/Lib/include/DbgHelpers.h:
--------------------------------------------------------------------------------
1 |
2 | // DbgHelpers.h
3 | // Defines and functions to help in debugging
4 | // Shishir Bhat (http://www.shishirbhat.com)
5 | // History
6 | // 06/23/13 Initial version
7 | //
8 |
9 | #ifndef _DBGHELPERS_H
10 | #define _DBGHELPERS_H
11 |
12 | #ifdef __cplusplus
13 | extern "C" {
14 | #endif
15 |
16 | /**
17 | * Original work from http://c.learncodethehardway.org/book/ex20.html
18 | * Modified/additions to my liking
19 | */
20 |
21 | #define logtrace(M, ...) fprintf(stderr, "[TRACE] " M "\n", ##__VA_ARGS__)
22 | #define logerr(M, ...) fprintf(stderr, "[ERROR] " M "(lastError: %u)\n", ##__VA_ARGS__, GetLastError())
23 | #define logwarn(M, ...) fprintf(stderr, "[WARN] " M "\n", ##__VA_ARGS__)
24 | #define loginfo(M, ...) fprintf(stderr, "[INFO] " M "\n", ##__VA_ARGS__)
25 |
26 | #ifdef _DEBUG
27 |
28 | #define logdbg(M, ...) fprintf(stdout, "[DEBUG] " M "\n", ##__VA_ARGS__)
29 |
30 | #define DBG_MEMSET(mem, size) ( memset(mem, 0xCE, size) )
31 |
32 | #else
33 | #define logdbg(M, ...)
34 |
35 | #define NDBG_MEMSET(mem, size) ( memset(mem, 0x00, size) )
36 | #define DBG_MEMSET(mem, size) NDBG_MEMSET(mem, size)
37 | #endif
38 |
39 | #ifdef __cplusplus
40 | }
41 | #endif
42 |
43 | #endif // _DBGHELPERS_H
44 |
--------------------------------------------------------------------------------
/Debugger/Inc/GuiDebugCommon.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Common.h"
4 | #include "UICreator.h"
5 |
6 | #define THTYPE_MAIN 0
7 | #define THTYPE_WORKER 1
8 |
9 | #define LV_REGS_NUMCOLUMNS 2
10 | #define LV_THREAD_NUMCOLUMNS 5
11 |
12 | #define FREEIF_GUIDBGCOMM(ptr) if(ptr && ptr->fFreeThis) { CHL_MmFree((void**)&ptr); }
13 |
14 | typedef int THTYPE;
15 |
16 | static WCHAR aszThreadTypes[][SLEN_COMMON32] = { L"Main", L"Worker" };
17 | static WCHAR *apszRegNames[] = { L"EAX", L"EBX", L"ECX", L"EDX", L"ESI", L"EDI", L"ESP", L"EBP", L"EIP" };
18 |
19 | typedef struct _GuiDbgComm {
20 | // Indicates whether the receiver must free this memory or not
21 | BOOL fFreeThis;
22 |
23 | // threadID which is sending/receiving the message
24 | DWORD dwThreadID;
25 |
26 | // tab index and handles to all tabitem children
27 | TABPAGEINFO stTabPageInfo;
28 |
29 | // Indicates whether Gui is sending the detach message due to debugger main window exit
30 | BOOL GD_fDetachOnDebuggerExit;
31 |
32 | }GUIDBGCOMM, *PGUIDBGCOMM;
33 |
34 | typedef struct ListView_ThreadInfo {
35 | DWORD dwThreadId;
36 | DWORD dwEIPLocation;
37 | WCHAR szFunction[SLEN_COMMON64];
38 | THTYPE thType;
39 | INT iThreadPri;
40 | }LV_THREADINFO, *PLV_THREADINFO;
41 |
--------------------------------------------------------------------------------
/Debugger/Inc/CustomEvents.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _CUSTOMEVENTS_H
3 | #define _CUSTOMEVENTS_H
4 |
5 | #include
6 |
7 | // Naming convention:
8 | // First two letters indicate source and destination. GD means Gui to Debug thread.
9 | // Second word indicates what the message is about(tab, menu items, ...)
10 | //
11 | #define GD_TAB_INFOCUS WM_USER
12 | #define GD_TAB_OUTFOCUS (WM_USER + 1)
13 |
14 | #define GD_MENU_CONTINUE (WM_USER + 2)
15 | #define GD_MENU_STEPINTO (WM_USER + 3)
16 | #define GD_MENU_STEPOVER (WM_USER + 4)
17 | #define GD_MENU_STEPOUT (WM_USER + 5)
18 | #define GD_MENU_BREAKALL (WM_USER + 6)
19 | #define GD_MENU_SUSPALL (WM_USER + 7)
20 | #define GD_MENU_RESALL (WM_USER + 8)
21 | #define GD_MENU_SUSPRES (WM_USER + 9)
22 |
23 | #define GD_SESS_TERM (WM_USER + 10)
24 | #define GD_SESS_DETACH (WM_USER + 11)
25 | #define GD_SESS_DUMPTERM (WM_USER + 12)
26 |
27 | #define DG_SESS_TERM (WM_USER + 70)
28 |
29 | // Start and end values for use in GetMessage()
30 | #define CUSTOM_GDEVENT_START GD_TAB_INFOCUS
31 | #define CUSTOM_GDEVENT_END GD_SESS_DUMPTERM
32 |
33 | // Start and end values of Debug->Gui messages
34 | #define CUSTOM_DGEVENT_START DG_SESS_TERM
35 | #define CUSTOM_DGEVENT_END DG_SESS_TERM
36 |
37 | #endif // _CUSTOMEVENTS_H
38 |
--------------------------------------------------------------------------------
/Debugger/Lib/include/ProcessFunctions.h:
--------------------------------------------------------------------------------
1 |
2 | // ProcessFunctions.h
3 | // Contains functions that provide IO operation services
4 | // Shishir Bhat (http://www.shishirbhat.com)
5 | // History
6 | // 03/25/14 Initial version
7 | // 09/09/14 Refactor to store defs in individual headers.
8 | // 09/12/14 Naming convention modifications
9 | //
10 |
11 | #ifndef _PROCESSFUNCTIONS_H
12 | #define _PROCESSFUNCTIONS_H
13 |
14 | #ifdef __cplusplus
15 | extern "C" {
16 | #endif
17 |
18 | #include "Defines.h"
19 |
20 | // Custom error codes
21 | #define CHLE_PROC_DOSHEADER 17150
22 | #define CHLE_PROC_TEXTSECHDR 17151
23 | #define CHLE_PROC_NOEXEC 17152
24 |
25 | // -------------------------------------------
26 | // Functions exported
27 |
28 | DllExpImp HRESULT CHL_PsGetProcNameFromID(_In_ DWORD pid, _Inout_z_ WCHAR *pwsProcName, _In_ DWORD dwBufSize);
29 | DllExpImp HRESULT CHL_PsGetNtHeaders(_In_ HANDLE hMapView, _Out_ PIMAGE_NT_HEADERS *ppstNtHeaders);
30 | DllExpImp HRESULT CHL_PsGetPtrToCode(
31 | _In_ DWORD dwFileBase,
32 | _In_ PIMAGE_NT_HEADERS pNTHeaders,
33 | _Out_ PDWORD pdwCodePtr,
34 | _Out_ PDWORD pdwSizeOfData,
35 | _Out_ PDWORD pdwCodeSecVirtAddr);
36 |
37 | DllExpImp HRESULT CHL_PsGetEnclosingSectionHeader(_In_ DWORD rva, _In_ PIMAGE_NT_HEADERS pNTHeader, _Out_ PIMAGE_SECTION_HEADER *ppstSecHeader);
38 |
39 | #ifdef __cplusplus
40 | }
41 | #endif
42 |
43 | #endif // _PROCESSFUNCTIONS_H
44 |
--------------------------------------------------------------------------------
/Debugger/DebuggerDP.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Inc\DebuggerDP.h"
3 |
4 | BOOL CALLBACK DebuggerDP(HWND hDlg, UINT message, WPARAM /*wParam*/, LPARAM lParam)
5 | {
6 | RECT rcOwner;
7 | // RECT rcTabAdjust;
8 |
9 | switch(message)
10 | {
11 | case WM_INITDIALOG:
12 | {
13 | HWND hTabParent = NULL;
14 |
15 | ASSERT(lParam);
16 |
17 | hTabParent = (HWND)lParam;
18 |
19 | // Get owner client rect so that I can fill up
20 | // the complete space of owner's client area
21 | RECT rcTemp;
22 | GetClientRect(hTabParent, &rcOwner);
23 | CopyRect(&rcTemp, &rcOwner);
24 | TabCtrl_AdjustRect(hTabParent, FALSE, &rcOwner);
25 |
26 | POINT p;
27 | p.x = rcOwner.left;
28 | p.y = rcOwner.top;
29 | ClientToScreen(hTabParent, &p);
30 |
31 | SetWindowPos(hDlg, HWND_TOP, p.x, p.y, rcOwner.right, rcOwner.bottom, SWP_SHOWWINDOW);
32 |
33 | return TRUE;
34 | }
35 |
36 | case WM_SIZE:
37 | {
38 | break;
39 | }
40 |
41 | case WM_COMMAND:
42 | {
43 | // handle commands from child controls
44 | //switch(LOWORD(wParam))
45 | //{
46 |
47 | //}
48 | return FALSE;
49 | }
50 |
51 | case WM_CLOSE:
52 | {
53 | EndDialog(hDlg, 0);
54 | return TRUE;
55 | }
56 |
57 | }// switch(message)
58 | return FALSE;
59 | }
60 |
--------------------------------------------------------------------------------
/Debugger/Lib/include/GuiFunctions.h:
--------------------------------------------------------------------------------
1 |
2 | // GuiFunctions.h
3 | // Contains functions that provide IO operation services
4 | // Shishir Bhat (http://www.shishirbhat.com)
5 | // History
6 | // 03/25/14 Initial version
7 | // 09/09/14 Refactor to store defs in individual headers.
8 | // 09/12/14 Naming convention modifications
9 | //
10 |
11 | #ifndef _GUIFUNCTIONS_H
12 | #define _GUIFUNCTIONS_H
13 |
14 | #ifdef __cplusplus
15 | extern "C" {
16 | #endif
17 |
18 | #include "Defines.h"
19 | #include "MemFunctions.h"
20 |
21 | // -------------------------------------------
22 | // Functions exported
23 |
24 | DllExpImp HRESULT CHL_GuiCenterWindow(_In_ HWND hWnd);
25 |
26 | // Given the window handle and the number of characters, returns the
27 | // width and height in pixels that will be occupied by a string of that
28 | // consisting of those number of characters
29 | DllExpImp HRESULT CHL_GuiGetTextArea(_In_ HWND hWindow, _In_ int nCharsInText, _Out_ int *pnPixelsWidth, _Out_ int *pnPixelsHeight);
30 |
31 | DllExpImp HRESULT CHL_GuiInitListViewColumns(
32 | _In_ HWND hList,
33 | _In_ WCHAR *apszColumNames[],
34 | _In_ int nColumns,
35 | _In_opt_ int *paiColumnSizePercent);
36 |
37 | DllExpImp HRESULT CHL_GuiAddListViewRow(
38 | _In_ HWND hList,
39 | _In_ WCHAR *apszItemText[],
40 | _In_ int nItems,
41 | _In_opt_ LPARAM lParam);
42 |
43 | #ifdef __cplusplus
44 | }
45 | #endif
46 |
47 | #endif // _GUIFUNCTIONS_H
48 |
--------------------------------------------------------------------------------
/Debugger/Dasm/DasmInc.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _DASMINC_H
3 | #define _DASMINC_H
4 |
5 | #include "..\Inc\Common.h"
6 |
7 | //#define UNIT_TESTS_ONLY
8 |
9 | // input file types assigned to g_dwInputFileType
10 | #define DASM_FTYPE_EXE 0x0001
11 | #define DASM_FTYPE_DLL 0x0002
12 |
13 | #define DASM_VERSION_STR L"0.9"
14 |
15 | #define MAX_CODE_PARTS 4
16 | #define CODE_PART_CODE 0
17 | #define CODE_PART_IAT 1
18 |
19 | /*
20 | * Structures
21 | */
22 | typedef struct _BINFILEINFO {
23 | PIMAGE_NT_HEADERS pNTHeaders; // pointer to NT headers when binary file mapped into memory
24 | DWORD dwVirtBaseOfCode; // ImageBase + BaseOfCode
25 | }BINFILEINFO;
26 |
27 | // struct: store the location of an area within the .text section
28 | // where there is no code (parts may be the IAT/...).
29 | typedef struct _NonCodeLoc {
30 | INT iPartType;
31 | DWORD dwFilePointer; // where in the file this part of code starts
32 | DWORD dwPartSize; // size of this part of code
33 | }NONCODE_LOC;
34 |
35 | // struct: Includes an array of NONCODE_LOC struct to specify the various
36 | // places in the .text/code section where there is no code but
37 | // other stuff like IAT.
38 | typedef struct _NCodeLocs {
39 | HANDLE hFileBase;
40 | INT nNonCodeParts;
41 | NONCODE_LOC aNonCodeLocs[MAX_CODE_PARTS];
42 | }NCODE_LOCS;
43 |
44 | // Function comment skeleton
45 | /* fGetPtrNTHeaders()
46 | *
47 | *
48 | * Args:
49 | *
50 | *
51 | * RetVal:
52 | *
53 | */
54 |
55 | #endif // _DASMINC_H
56 |
--------------------------------------------------------------------------------
/Debugger/Lib/include/Assert.h:
--------------------------------------------------------------------------------
1 |
2 | // Assert.h
3 | // Contains functions that provides the ASSERT() service
4 | // Shishir Bhat (http://www.shishirbhat.com)
5 | // History
6 | // 06/23/13 Initial version
7 | //
8 |
9 | /********************************************************************************************
10 | * ASSERT(x) is a debug-mode-only macro that is used to catch errors that must not
11 | * occur when software is released. It finds out bugs in the coding phase rather than
12 | * the testing phase.
13 | *
14 | * ASSERT accepts a relational expression as a macro-argument and tests whether it is
15 | * true. If it is true, nothing is done. If it is false, the user-defined _Assert()
16 | * function is called which prints the line number and filename in which the assertion
17 | * failed.
18 | *
19 | * Debug-mode-only is achieved using the #ifdef directive.
20 | * Code is compiled using Visual Studio 2010, which defines the macro _DEBUG in debug-mode.
21 | * In debug-mode _DEBUG is defined and in release-mode it is not defined.
22 | *******************************************************************************************/
23 |
24 | #ifndef _ASSERT_H
25 | #define _ASSERT_H
26 |
27 | #ifdef __cplusplus
28 | extern "C" {
29 | #endif
30 |
31 | #include
32 | #include
33 |
34 | #ifdef _DEBUG
35 | void vAssert(const char* psFile, unsigned int uLine);
36 | #define ASSERT(x) \
37 | if(x) {} \
38 | else \
39 | vAssert(__FILE__, __LINE__)
40 | #else
41 | #define ASSERT(x)
42 | #endif
43 |
44 | #ifdef __cplusplus
45 | }
46 | #endif
47 |
48 | #endif // _ASSERT_H
49 |
--------------------------------------------------------------------------------
/Debugger/Inc/Breakpoint.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _BREAKPOINTS_H
3 | #define _BREAKPOINTS_H
4 |
5 | #include "Common.h"
6 | #include "Defines.h"
7 | #include "StringLengths.h"
8 | #include "Defines.h"
9 | #include "DebugCommon.h"
10 |
11 | #define BPTYPE_USERSINGLEHIT 0x0001 // for single stepping (step {out|over}), run to cursor
12 | #define BPTYPE_USERMULTIHIT 0x0002 // user specified
13 | #define BPTYPE_DEBUGGERSINGLEHIT 0x0004
14 | #define BPTYPE_DEBUGGERMULTIHIT 0x0008
15 |
16 | #define BPTYPE_ASMLEVEL 0x0010 // breakpoint at a specific address target memory
17 | #define BPTYPE_SOURCELEVEL 0x0020 // breakpoint at a line number in a source file related to a specific exe/dll
18 |
19 | typedef struct _ActualBreakpoint {
20 | BOOL fResolved;
21 | DWORD dwAddrInTarget;
22 | BYTE bOrigCodeByte;
23 | }ACTUALBP, *PACTUALBP;
24 |
25 | // The below structure is the one stored as the linked list node
26 | typedef struct _Breakpoint {
27 | int id;
28 | int nReferences;
29 |
30 | BPTYPE bpType;
31 |
32 | int iLineNum;
33 | WCHAR szExecutableName[SLEN_MAXPATH];
34 | WCHAR szSourceFileName[SLEN_MAXPATH];
35 |
36 | ACTUALBP stActualBp;
37 | }BREAKPOINT, *PBREAKPOINT;
38 |
39 | // ** Functions **
40 | BOOL fBpInitialize(__out PBPLIST *ppBreakpoints);
41 | BOOL fBpTerminate(PBPLIST pBreakpoints);
42 |
43 | BOOL fBpInsert(PBPLIST pstBpList, PBPINFO pstBpInfo, PTARGETINFO pstTargetInfo, __out OPTIONAL PINT piBpID);
44 | BOOL fBpRemove(PBPLIST pstBpList, PBPINFO pstBpInfo, PTARGETINFO pstTargetInfo);
45 | BOOL fBpFind(PBPLIST pstBpList, __inout PBPINFO pstBpInfo, PINT piBpID);
46 |
47 | #endif // _BREAKPOINTS_H
48 |
--------------------------------------------------------------------------------
/Debugger/Inc/DebugHelpers.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _DEBUGTHREADHELPERS_H
3 | #define _DEBUGTHREADHELPERS_H
4 |
5 | #include "Common.h"
6 | #include "Defines.h"
7 | #include "DebugCommon.h"
8 | #include "GuiDebugCommon.h"
9 |
10 | // Bit number of the TrapFlag in EFlags register
11 | #define BITPOS_EFLAGS_TF 8
12 |
13 | BOOL fGetExceptionName(DWORD excode, __out WCHAR *pwsBuffer, int bufSize);
14 |
15 | BOOL fAddThread(CHL_HTABLE *phtThreads, DWORD dwThreadId, LPCREATE_THREAD_DEBUG_INFO lpThreadInfo);
16 | BOOL fRemoveThread(CHL_HTABLE *phtThreads, DWORD dwThreadId, __out LPCREATE_THREAD_DEBUG_INFO lpThreadInfo);
17 | BOOL fGetThreadHandle(CHL_HTABLE *phtThreads, DWORD id, __out HANDLE *phThread);
18 | BOOL fDeleteThreadsTable(CHL_HTABLE *phtThreads);
19 | BOOL fSuspendAllThreads(CHL_HTABLE *phtThreads);
20 | BOOL fResumeAllThreads(CHL_HTABLE *phtThreads);
21 | BOOL fIsNtDllLoaded(CHL_HTABLE *phtDllTable, __out DWORD *pdwBaseAddress);
22 |
23 | // Breakpoint functions
24 | BOOL fBreakAtEntryPoint(PTARGETINFO pstTargetInfo);
25 | BOOL fHandleExceptionBreakpoint(PTARGETINFO pstTargetInfo, __out PDWORD pdwContinueStatus);
26 | BOOL fReInsertBPIf(PTARGETINFO pstTargetInfo, PREVBPINFO *pstBpInfo);
27 | BOOL fDecrementInstPointer(CHL_HTABLE *phtThreads, DWORD dwThreadId);
28 | BOOL fSetTrapFlag(CHL_HTABLE *phtThreads, DWORD dwThreadId);
29 | BOOL fClearTrapFlag(CHL_HTABLE *phtThreads, DWORD dwThreadId);
30 |
31 | void vSetContinueStatusFromUser(DWORD dwExceptionCode, DWORD dwExceptionAddress, BOOL fFirstChance, PDWORD pdwContinueStatus);
32 |
33 | // Debugger state changes
34 | void vSetMenuItemsState(PTARGETINFO pstTargetInfo);
35 | void vDebuggerStateChange(PTARGETINFO pstTargetInfo, int iNewState);
36 |
37 | // Gui management
38 | BOOL fUpdateThreadsListView(HWND hList, CHL_HTABLE *phtThreads, HANDLE hMainThread);
39 | BOOL fUpdateRegistersListView(HWND hList, DWORD dwThreadId);
40 | BOOL fShowDisassembly(PTARGETINFO pstTargetInfo, DWORD dwStartFromTargetAddress);
41 |
42 | #endif // _DEBUGTHREADHELPERS_H
43 |
--------------------------------------------------------------------------------
/Debugger/Lib/include/InternalDefines.h:
--------------------------------------------------------------------------------
1 |
2 | // Defines.h
3 | // Contains common #defines, typedefs and data structures
4 | // Shishir Bhat (http://www.shishirbhat.com)
5 | // History
6 | // 09/18/2014 Standardize keys and value types.
7 | // 08/04/2015 Make individual headers usable by clients.
8 | // 01/19/2016 Provide a way to test if a CHL_VAL is occupied or not.
9 | //
10 |
11 | #ifndef CHL_INT_DEFINES_H
12 | #define CHL_INT_DEFINES_H
13 |
14 | #include "CommonInclude.h"
15 | #include "Assert.h"
16 | #include "DbgHelpers.h"
17 | #include "Helpers.h"
18 | #include "Defines.h"
19 |
20 | // -------------------------------------------
21 | // #defs and typedefs
22 |
23 | #define IS_VALID_CHL_VALTYPE(vt) (((vt) > CHL_VT_START) && ((vt) < CHL_VT_END))
24 | #define IS_INVALID_CHL_VALTYPE(vt) (! IS_VALID_CHL_VALTYPE(vt))
25 |
26 | #define IS_VALID_CHL_KEYTYPE(kt) (((kt) > CHL_KT_START) && ((kt) < CHL_KT_END))
27 | #define IS_INVALID_CHL_KEYTYPE(kt) (! IS_VALID_CHL_KEYTYPE(kt))
28 |
29 | // Magic number denoting that a CHL_VAL is currently occupied
30 | // This is actually prime number 433494437 (see https://en.wikipedia.org/wiki/List_of_prime_numbers#Markov_primes)
31 | #define MAGIC_CHLVAL_OCCUPIED ((UINT)0x19D699A5)
32 |
33 | // -------------------------------------------
34 | // Functions internal only
35 |
36 | HRESULT _CopyKeyIn(_In_ PCHL_KEY pChlKey, _In_ CHL_KEYTYPE keyType, _In_ PCVOID pvKey, _Inout_opt_ int iKeySize);
37 | HRESULT _CopyKeyOut
38 | (
39 | _In_ PCHL_KEY pChlKey,
40 | _In_ CHL_KEYTYPE keyType,
41 | _Inout_ PVOID pvKeyOut,
42 | _Inout_opt_ PINT pKeyOutSize,
43 | _In_ BOOL fGetPointerOnly
44 | );
45 | BOOL _IsDuplicateKey(_In_ PCHL_KEY pChlLeftKey, _In_ PCVOID pvRightKey, _In_ CHL_KEYTYPE keyType, _In_ int iKeySize);
46 | void _DeleteKey(_In_ PCHL_KEY pChlKey, _In_ CHL_KEYTYPE keyType);
47 | HRESULT _GetKeySize(_In_ PVOID pvKey, _In_ CHL_KEYTYPE keyType, _Inout_ PINT piKeySize);
48 | HRESULT _EnsureSufficientKeyBuf(
49 | _In_ PCHL_KEY pChlKey,
50 | _In_ int iSpecBufSize,
51 | _Inout_opt_ PINT piReqBufSize);
52 |
53 | HRESULT _CopyValIn(_In_ PCHL_VAL pChlVal, _In_ CHL_VALTYPE valType, _In_ PCVOID pvVal, _Inout_opt_ int iValSize);
54 | HRESULT _CopyValOut
55 | (
56 | _In_ PCHL_VAL pChlVal,
57 | _In_ CHL_VALTYPE valType,
58 | _Inout_ PVOID pvValOut,
59 | _Inout_opt_ PINT pValOutSize,
60 | _In_ BOOL fGetPointerOnly
61 | );
62 | BOOL _IsDuplicateVal(_In_ PCHL_VAL pLeftVal, _In_ PCVOID pRightVal, _In_ CHL_VALTYPE valType, _In_ int iValSize);
63 | void _DeleteVal(_In_ PCHL_VAL pChlVal, _In_ CHL_VALTYPE valType, _In_opt_ BOOL fFreePointerType);
64 | void _MarkValUnoccupied(_In_ PCHL_VAL pChlVal);
65 | void _MarkValOccupied(_In_ PCHL_VAL pChlVal);
66 | BOOL _IsValOccupied(_In_ PCHL_VAL pChlVal);
67 | HRESULT _GetValSize(_In_ PVOID pvVal, _In_ CHL_VALTYPE valType, _Inout_ PINT piValSize);
68 | HRESULT _EnsureSufficientValBuf(
69 | _In_ PCHL_VAL pChlVal,
70 | _In_ int iSpecBufSize,
71 | _Inout_opt_ PINT piReqBufSize);
72 |
73 | #endif // CHL_INT_DEFINES_H
74 |
--------------------------------------------------------------------------------
/Debugger/Lib/include/Queue.h:
--------------------------------------------------------------------------------
1 |
2 | // Queue.h
3 | // Contains functions that provide IO operation services
4 | // Shishir Bhat (http://www.shishirbhat.com)
5 | // History
6 | // Unknown history!
7 | // 09/09/14 Refactor to store defs in individual headers.
8 | //
9 |
10 | #ifndef _CHL_QUEUE_H
11 | #define _CHL_QUEUE_H
12 |
13 | #ifdef __cplusplus
14 | extern "C" {
15 | #endif
16 |
17 | #include "Defines.h"
18 | #include "LinkedList.h"
19 | #include "MemFunctions.h"
20 |
21 | // A Queue object structure
22 | typedef struct _Queue CHL_QUEUE, *PCHL_QUEUE;
23 | struct _Queue
24 | {
25 | int nCapacity; // unused currently
26 | int nCurItems;
27 | PCHL_LLIST pList;
28 |
29 | // Access Methods
30 |
31 | HRESULT (*Create)
32 | (
33 | _Out_ PCHL_QUEUE *ppQueueObj,
34 | _In_ CHL_VALTYPE valType,
35 | _In_opt_ int nEstimatedItems
36 | );
37 |
38 | HRESULT (*Destroy)
39 | (
40 | _In_ PCHL_QUEUE pThis
41 | );
42 |
43 | HRESULT (*Insert)
44 | (
45 | _In_ PCHL_QUEUE pQueueObj,
46 | _In_ PCVOID pvValue,
47 | _In_ int nValSize
48 | );
49 |
50 | HRESULT (*Delete)
51 | (
52 | _In_ PCHL_QUEUE pQueueObj,
53 | _Inout_opt_ PVOID pValOut,
54 | _Inout_opt_ PINT piValBufSize,
55 | _In_opt_ BOOL fGetPointerOnly
56 | );
57 |
58 | HRESULT (*Peek)
59 | (
60 | _In_ PCHL_QUEUE pQueueObj,
61 | _Inout_opt_ PVOID pValOut,
62 | _Inout_opt_ PINT piValBufSize,
63 | _In_opt_ BOOL fGetPointerOnly
64 | );
65 |
66 | HRESULT(*Find)
67 | (
68 | _In_ PCHL_QUEUE pQueueObj,
69 | _In_ PCVOID pvValue,
70 | _In_ CHL_CompareFn pfnComparer,
71 | _In_opt_ PVOID pvValOut,
72 | _In_opt_ PINT piValBufSize,
73 | _In_opt_ BOOL fGetPointerOnly
74 | );
75 | };
76 |
77 | // -------------------------------------------
78 | // Functions exported
79 |
80 | DllExpImp HRESULT CHL_DsCreateQ
81 | (
82 | _Out_ PCHL_QUEUE *ppQueueObj,
83 | _In_ CHL_VALTYPE valType,
84 | _In_opt_ int nEstimatedItems
85 | );
86 |
87 | DllExpImp HRESULT CHL_DsDestroyQ(_In_ PCHL_QUEUE pQueueObj);
88 |
89 | DllExpImp HRESULT CHL_DsInsertQ
90 | (
91 | _In_ PCHL_QUEUE pQueueObj,
92 | _In_ PCVOID pvValue,
93 | _In_ int nValSize
94 | );
95 |
96 | DllExpImp HRESULT CHL_DsDeleteQ
97 | (
98 | _In_ PCHL_QUEUE pQueueObj,
99 | _Inout_opt_ PVOID pValOut,
100 | _Inout_opt_ PINT piValBufSize,
101 | _In_opt_ BOOL fGetPointerOnly
102 | );
103 |
104 | DllExpImp HRESULT CHL_DsPeekQ
105 | (
106 | _In_ PCHL_QUEUE pQueueObj,
107 | _Inout_opt_ PVOID pValOut,
108 | _Inout_opt_ PINT piValBufSize,
109 | _In_opt_ BOOL fGetPointerOnly
110 | );
111 |
112 | DllExpImp HRESULT CHL_DsFindQ
113 | (
114 | _In_ PCHL_QUEUE pQueueObj,
115 | _In_ PCVOID pvValue,
116 | _In_ CHL_CompareFn pfnComparer,
117 | _In_opt_ PVOID pvValOut,
118 | _In_opt_ PINT piValBufSize,
119 | _In_opt_ BOOL fGetPointerOnly
120 | );
121 |
122 | #ifdef __cplusplus
123 | }
124 | #endif
125 |
126 | #endif // _CHL_QUEUE_H
--------------------------------------------------------------------------------
/Debugger/Lib/include/Defines.h:
--------------------------------------------------------------------------------
1 |
2 | // Defines.h
3 | // Contains common #defines, typedefs and data structures
4 | // Shishir Bhat (http://www.shishirbhat.com)
5 | // History
6 | // 09/09/2014 Refactor to store defs in individual headers.
7 | // 08/04/2015 Make individual headers usable by clients.
8 | // 01/19/2016 Provide a way to test if a CHL_VAL is occupied or not.
9 | //
10 |
11 | #ifndef CHL_DEFINES_H
12 | #define CHL_DEFINES_H
13 |
14 | #include
15 | #include
16 |
17 | // -------------------------------------------
18 | // #defs and typedefs
19 |
20 | #ifdef CHELPLIB_EXPORTS
21 | #define DllExpImp __declspec( dllexport )
22 | #else
23 | #define DllExpImp __declspec( dllimport )
24 | #endif // CHELPLIB_EXPORTS
25 |
26 | #ifndef PCVOID
27 | typedef PVOID const PCVOID;
28 | #endif
29 |
30 | // A generic compare function used to compare either two keys or two values.
31 | // The function must return -
32 | // 0 if both left and right are equal
33 | // 1 if right is greater than left
34 | // -1 if right is lesser than left
35 | typedef int (*CHL_CompareFn)(_In_ PCVOID pvLeft, _In_ PCVOID pvRight);
36 |
37 | // -------------------------------------------
38 | // Structures
39 |
40 | union _tagCHL_KEYDEF {
41 | PSTR pszKey;
42 | PWSTR pwszKey;
43 | int iKey;
44 | UINT uiKey;
45 | PVOID pvKey;
46 | };
47 |
48 | union _tagCHL_VALDEF {
49 | int iVal;
50 | UINT uiVal;
51 | double dVal;
52 | PSTR pszVal; // Pointer to ANSI string(value is allocated on heap)
53 | PWSTR pwszVal; // Pointer to wide string(value is allocated on heap)
54 | PVOID pvPtr; // Stores a pointer(any type)(value is allocated on heap)
55 | PVOID pvUserObj; // Pointer to user object(value is allocated on heap)
56 | };
57 |
58 | typedef struct CHL_KEY
59 | {
60 | // Num. of bytes as size of key
61 | int iKeySize;
62 |
63 | // Storage for the key
64 | union _tagCHL_KEYDEF keyDef;
65 |
66 | }CHL_KEY, *PCHL_KEY;
67 |
68 | typedef struct CHL_VAL
69 | {
70 | // Num. of bytes as size of val
71 | int iValSize;
72 |
73 | // Magic number to denote whether occupied or not
74 | UINT magicOccupied;
75 |
76 | // Storage for the value
77 | union _tagCHL_VALDEF valDef;
78 |
79 | }CHL_VAL, *PCHL_VAL;
80 |
81 | // -------------------------------------------
82 | // Enumerations
83 |
84 | // Key Types
85 | typedef enum
86 | {
87 | // Invalid value type
88 | CHL_KT_START,
89 |
90 | // Signed 32bit integer
91 | CHL_KT_INT32,
92 |
93 | // Unsigned 32bit integer
94 | CHL_KT_UINT32,
95 |
96 | // A pointer whose pointed-to address is the key
97 | CHL_KT_POINTER,
98 |
99 | // Null-terminated ANSI string
100 | CHL_KT_STRING,
101 |
102 | // Null-terminated Unicode(wide char) string
103 | CHL_KT_WSTRING,
104 |
105 | // Invalid value type
106 | CHL_KT_END
107 | }CHL_KEYTYPE;
108 |
109 | // Value Types
110 | typedef enum
111 | {
112 | // Invalid value type
113 | CHL_VT_START,
114 |
115 | // Signed 32bit integer
116 | CHL_VT_INT32,
117 |
118 | // Unsigned 32bit integer
119 | CHL_VT_UINT32,
120 |
121 | // Pointer of any type(pointed-to address is the value stored)
122 | CHL_VT_POINTER,
123 |
124 | // Any user object(data structure).
125 | CHL_VT_USEROBJECT,
126 |
127 | // Null-terminated ANSI string
128 | CHL_VT_STRING,
129 |
130 | // Null-terminated Unicode(wide char) string
131 | CHL_VT_WSTRING,
132 |
133 | // Invalid value type
134 | CHL_VT_END
135 | }CHL_VALTYPE;
136 |
137 | #endif // CHL_DEFINES_H
138 |
--------------------------------------------------------------------------------
/Debugger/MenuItems.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Inc\MenuItems.h"
3 |
4 | static void vOpenProgramProcess(HMENU hMenu, DWORD dwChangeTo);
5 | static void vTargetControl(HMENU hMenu, DWORD dwChangeTo);
6 |
7 | // vMiDebuggerInit()
8 | //
9 | void vMiDebuggerInit(HMENU hMenu)
10 | {
11 | ASSERT(ISVALID_HANDLE(hMenu));
12 |
13 | // Everything is enabled by default when program starts up
14 | // So disable the target controls since no target is loaded at init
15 | vTargetControl(hMenu, MF_GRAYED);
16 | return;
17 | }
18 |
19 | // vMiDebugSessionStart()
20 | //
21 | void vMiDebugSessionStart(HMENU hMenu)
22 | {
23 | ASSERT(ISVALID_HANDLE(hMenu));
24 |
25 | vTargetControl(hMenu, MF_ENABLED);
26 | vOpenProgramProcess(hMenu, MF_GRAYED);
27 | return;
28 | }
29 |
30 | // vMiDebugSessionEnd()
31 | //
32 | void vMiDebugSessionEnd(HMENU hMenu)
33 | {
34 | ASSERT(ISVALID_HANDLE(hMenu));
35 |
36 | vOpenProgramProcess(hMenu, MF_ENABLED);
37 | vTargetControl(hMenu, MF_GRAYED);
38 | return;
39 | }
40 |
41 | void vMiDebuggerRunning(HMENU hMenu)
42 | {
43 | vOpenProgramProcess(hMenu, MF_GRAYED);
44 |
45 | EnableMenuItem(hMenu, IDM_TERMINATETARGET, MF_ENABLED);
46 | EnableMenuItem(hMenu, IDM_DETACHFROMTARGET, MF_ENABLED);
47 | EnableMenuItem(hMenu, IDM_DUMPANDTERMINATETARGET, MF_ENABLED);
48 |
49 | EnableMenuItem(hMenu, IDM_BREAKINTOTARGET, MF_ENABLED);
50 |
51 | EnableMenuItem(hMenu, IDM_SUSPENDALLTHREADS, MF_ENABLED);
52 | EnableMenuItem(hMenu, IDM_RESUMEALLTHREADS, MF_ENABLED);
53 | EnableMenuItem(hMenu, IDM_SUSPRESUME, MF_GRAYED);
54 |
55 | EnableMenuItem(hMenu, IDM_CONTINUE, MF_GRAYED);
56 | EnableMenuItem(hMenu, IDM_STEPINTO, MF_GRAYED);
57 | EnableMenuItem(hMenu, IDM_STEPOVER, MF_GRAYED);
58 | EnableMenuItem(hMenu, IDM_STEPOUT, MF_GRAYED);
59 | }
60 |
61 | void vMiDebuggerDebugging(HMENU hMenu)
62 | {
63 | EnableMenuItem(hMenu, IDM_TERMINATETARGET, MF_ENABLED);
64 | EnableMenuItem(hMenu, IDM_DETACHFROMTARGET, MF_ENABLED);
65 | EnableMenuItem(hMenu, IDM_DUMPANDTERMINATETARGET, MF_ENABLED);
66 |
67 | EnableMenuItem(hMenu, IDM_BREAKINTOTARGET, MF_GRAYED);
68 |
69 | // TODO: can we suspend /resume threads when the target has been suspended?
70 | EnableMenuItem(hMenu, IDM_SUSPENDALLTHREADS, MF_GRAYED);
71 | EnableMenuItem(hMenu, IDM_RESUMEALLTHREADS, MF_GRAYED);
72 | EnableMenuItem(hMenu, IDM_SUSPRESUME, MF_GRAYED);
73 |
74 | EnableMenuItem(hMenu, IDM_CONTINUE, MF_ENABLED);
75 | EnableMenuItem(hMenu, IDM_STEPINTO, MF_ENABLED);
76 | EnableMenuItem(hMenu, IDM_STEPOVER, MF_ENABLED);
77 | EnableMenuItem(hMenu, IDM_STEPOUT, MF_ENABLED);
78 | }
79 |
80 | static void vOpenProgramProcess(HMENU hMenu, DWORD dwChangeTo)
81 | {
82 | EnableMenuItem(hMenu, IDM_DEBUGPROGRAM, dwChangeTo);
83 | EnableMenuItem(hMenu, IDM_DEBUGPROCESS, dwChangeTo);
84 | }
85 |
86 | static void vTargetControl(HMENU hMenu, DWORD dwChangeTo)
87 | {
88 | EnableMenuItem(hMenu, IDM_TERMINATETARGET, dwChangeTo);
89 | EnableMenuItem(hMenu, IDM_DETACHFROMTARGET, dwChangeTo);
90 | EnableMenuItem(hMenu, IDM_DUMPANDTERMINATETARGET, dwChangeTo);
91 |
92 | EnableMenuItem(hMenu, IDM_CONTINUE, dwChangeTo);
93 | EnableMenuItem(hMenu, IDM_STEPINTO, dwChangeTo);
94 | EnableMenuItem(hMenu, IDM_STEPOVER, dwChangeTo);
95 | EnableMenuItem(hMenu, IDM_STEPOUT, dwChangeTo);
96 |
97 | EnableMenuItem(hMenu, IDM_BREAKINTOTARGET, dwChangeTo);
98 |
99 | EnableMenuItem(hMenu, IDM_SUSPENDALLTHREADS, dwChangeTo);
100 | EnableMenuItem(hMenu, IDM_RESUMEALLTHREADS, dwChangeTo);
101 | EnableMenuItem(hMenu, IDM_SUSPRESUME, dwChangeTo);
102 | }
--------------------------------------------------------------------------------
/Debugger/Inc/DebugCommon.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _DEBUGCOMMON_H
3 | #define _DEBUGCOMMON_H
4 |
5 | #include "Common.h"
6 | #include "UICreator.h"
7 | #include "Defines.h"
8 |
9 | #define DSTATE_INVALID 0
10 |
11 | // Target process is running and is not stopped by the debugger
12 | #define DSTATE_RUNNING 1
13 |
14 | // DO NOT process debug event loop, just wait for user input
15 | // and take action accordingly
16 | #define DSTATE_DEBUGGING 2
17 |
18 | // User is single stepping(step into)
19 | // Before: we are waiting for user input, DO NOT process debug event loop
20 | // After: user has pressed step into, process debug event loop(expect a SS exception)
21 | #define DSTATE_SINGLESTEP_BEFORE 3
22 | #define DSTATE_SINGLESTEP_AFTER 4
23 |
24 | // Debugger is using single step for its own purpose
25 | #define DSTATE_SINGLESTEP_DBG 5
26 |
27 | #define DSTATE_WAITFOR_DBGBREAK 6
28 |
29 | // Set by the Gui message loop handler or the debug event loop handler
30 | // indicating that the debug thread must exit now. This will be used
31 | // when the target process exits(either by itself or we killed it) or
32 | // we detach from it.
33 | #define DSTATE_EXIT 7
34 |
35 | // State after breakpoint hit. We must wait for user input and DO NOT
36 | // let target process continue execution when in this state
37 | #define DSTATE_BREAKPOINTWAIT DSTATE_DEBUGGING
38 |
39 | #define DSTATE_START DSTATE_INVALID
40 | #define DSTATE_END DSTATE_EXIT
41 |
42 | // Action the user specified when an unexpected BP was encountered
43 | #define DBG_CONTCUSTOM_ABORT 10
44 | #define DBG_CONTCUSTOM_BREAK 11
45 |
46 | #define MAX_BREAKPOINTS 256 // maximum logical breakpoints
47 |
48 | typedef int BPTYPE; // specifies breakpoint type
49 |
50 | typedef struct _BreakpointInterface {
51 | int aiIdentifiers[MAX_BREAKPOINTS];
52 | PCHL_LLIST pstLinkedListBp;
53 | }BPLIST, *PBPLIST;
54 |
55 | // Structure used to pass BP info between caller and callee
56 | typedef struct _BpInfo {
57 | int id; // specify when removing a breakpoint
58 | BPTYPE iBpType;
59 |
60 | PWCHAR pszExecutableName;
61 | PWCHAR pszSourceFileName;
62 | int iLineNum;
63 |
64 | DWORD dwTargetAddr;
65 |
66 | }BPINFO, *PBPINFO;
67 |
68 | typedef struct _DebugInfo {
69 | BOOL fDebuggingActiveProcess;
70 | BOOL fBreakAtMain;
71 | WCHAR szTargetPath[SLEN_MAXPATH];
72 | DWORD dwProcessID;
73 | HWND hMainWindow;
74 | HMENU hMainMenu;
75 | WCHAR szInitSyncEvtName[SLEN_EVENTNAMES];
76 | TABPAGEINFO stTabPageInfo;
77 | }DEBUGINFO, *PDEBUGINFO;
78 |
79 | typedef struct _PrevBpInfo {
80 | // Breakpoint hit in which target thread
81 | DWORD dwThreadId;
82 |
83 | // Info about the breakpoint that was hit
84 | BPINFO stBpInfo;
85 | }PREVBPINFO;
86 |
87 | typedef struct _TargetInfo {
88 | PDEBUGINFO pstDebugInfoFromGui;
89 |
90 | BOOL fCreateProcessEventRecvd;
91 |
92 | DWORD dwPID;
93 | DWORD dwMainThreadID;
94 |
95 | CREATE_PROCESS_DEBUG_INFO stProcessInfo;
96 |
97 | HANDLE hFileMapObj;
98 | HANDLE hFileMapView;
99 |
100 | PIMAGE_NT_HEADERS pstNtHeaders;
101 | DWORD dwCodeStart;
102 | DWORD dwCodeSize;
103 | DWORD dwCodeSecVirtAddr;
104 |
105 | CHL_HTABLE *phtDllsLoaded;
106 | CHL_HTABLE *phtThreads;
107 | PBPLIST pListBreakpoint;
108 | PREVBPINFO stPrevBpInfo;
109 |
110 | // To store info during single stepping (using TF)
111 | DWORD dwSSThreadId;
112 | DWORD dwSSTargetAddr;
113 |
114 | int nCurThreads;
115 | int nTotalProcesses;
116 | int nTotalThreads;
117 |
118 | int nCurDllsLoaded;
119 | int nTotalDllsLoaded;
120 |
121 | int iDebugState;
122 | int iPrevDebugState;
123 |
124 | BOOL fDetachOnDebuggerExit;
125 |
126 | LPDEBUG_EVENT lpDebugEvent;
127 | }TARGETINFO, *PTARGETINFO;
128 |
129 | #endif // _DEBUGCOMMON_H
130 |
--------------------------------------------------------------------------------
/Debugger/WinMain.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Inc\Common.h"
3 | #include "Inc\WndProc.h"
4 | #include "Inc\UICommon.h"
5 | #include "Inc\Logger.h"
6 |
7 | #define WNDSIZE_WIDTH 1024
8 | #define WNDSIZE_HEIGHT 768
9 |
10 | HINSTANCE g_hMainInstance;
11 |
12 | LOGGER StLogger;
13 | PLOGGER pstLogger = &StLogger;
14 |
15 | int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
16 | {
17 | HWND g_hMainWnd;
18 | MSG MainWndMsg;
19 | WNDCLASS MainWndClass;
20 |
21 | HACCEL hAccel;
22 |
23 | WCHAR szAppName[SLEN_COMMON64];
24 |
25 | int iScreenX, iScreenY, iWndX, iWndY, iWidth, iHeight;
26 | RECT rcMainWnd;
27 |
28 | DBG_UNREFERENCED_PARAMETER(szCmdLine);
29 | DBG_UNREFERENCED_PARAMETER(hPrevInstance);
30 |
31 | // First, initialize logger
32 | if(!fInitializeLogger(L"OSD_Log.txt", &StLogger))
33 | {
34 | MessageBox(NULL, L"Cannot initialize logger", L"Error", MB_ICONEXCLAMATION);
35 | return CE_WMAIN_ERROR;
36 | }
37 |
38 | g_hMainInstance = hInstance;
39 |
40 | LoadString(GetModuleHandle(NULL), IDS_PGMNAME, szAppName, _countof(szAppName));
41 |
42 | // UI Window Class
43 | MainWndClass.style = CS_HREDRAW | CS_VREDRAW;
44 | MainWndClass.lpfnWndProc = WndProc;
45 | MainWndClass.cbClsExtra = 0;
46 | MainWndClass.cbWndExtra = 0;
47 | MainWndClass.hInstance = g_hMainInstance;
48 | MainWndClass.hIcon = NULL;
49 | MainWndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
50 | MainWndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
51 | MainWndClass.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU);
52 | MainWndClass.lpszClassName = szAppName;
53 |
54 | if(!RegisterClass(&MainWndClass))
55 | {
56 | MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
57 | return CE_WMAIN_ERROR;
58 | }
59 |
60 | // Initialize common controls
61 | InitCommonControls();
62 |
63 | // Create the main window
64 | g_hMainWnd = CreateWindow(szAppName, // class name
65 | szAppName, // caption
66 | WS_CAPTION |
67 | WS_MINIMIZEBOX |
68 | WS_SYSMENU, // window style
69 | CW_USEDEFAULT, // initial X position
70 | CW_USEDEFAULT, // initial Y position
71 | WNDSIZE_WIDTH, // initial X size
72 | WNDSIZE_HEIGHT, // initial Y size
73 | NULL, // parent window handle
74 | NULL, // window menu handle
75 | g_hMainInstance, // program instance handle
76 | NULL);
77 |
78 | // exit if window was not created
79 | if( !g_hMainWnd )
80 | {
81 | MessageBox(0, L"Main Window creation error. Cannot continue.", 0, 0);
82 | return CE_WMAIN_ERROR;
83 | }
84 |
85 | // Init accelerators
86 | hAccel = LoadAccelerators(g_hMainInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
87 | if(!hAccel)
88 | {
89 | MessageBox(g_hMainWnd, L"Initialization failed. See log file.", L"Error", MB_OK | MB_ICONSTOP);
90 | logerror(pstLogger, L"LoadAccelerators() failed %u", GetLastError());
91 | return CE_WMAIN_ERROR;
92 | }
93 |
94 | // centre the main window in the screen
95 |
96 | // get the screen co-ordinates
97 | iScreenX = GetSystemMetrics(SM_CXSCREEN);
98 | iScreenY = GetSystemMetrics(SM_CYSCREEN);
99 |
100 | // get window rect and calculate the main window dimensions
101 | GetWindowRect(g_hMainWnd, &rcMainWnd);
102 | iWidth = rcMainWnd.right - rcMainWnd.left;
103 | iHeight = rcMainWnd.bottom - rcMainWnd.top;
104 |
105 | // calculate the new co-ordinates for the main window
106 | iWndX = iScreenX / 2 - iWidth / 2;
107 | iWndY = iScreenY / 2 - iHeight / 2;
108 |
109 | MoveWindow(g_hMainWnd, iWndX, iWndY, iWidth, iHeight, FALSE);
110 |
111 | ShowWindow(g_hMainWnd, iCmdShow);
112 | UpdateWindow(g_hMainWnd);
113 |
114 | while( GetMessage(&MainWndMsg, NULL, 0, 0) )
115 | {
116 | if(!TranslateAccelerator(g_hMainWnd, hAccel, &MainWndMsg))
117 | {
118 | TranslateMessage(&MainWndMsg);
119 | DispatchMessage(&MainWndMsg);
120 | }
121 | }
122 |
123 | return MainWndMsg.wParam;
124 | }
125 |
--------------------------------------------------------------------------------
/Debugger/Lib/include/LinkedList.h:
--------------------------------------------------------------------------------
1 |
2 | // LinkedList.h
3 | // Contains functions that implement a linked list data structure
4 | // Shishir Bhat (http://www.shishirbhat.com)
5 | // History
6 | // 04/05/14 Initial version
7 | // 09/09/14 Refactor to store defs in individual headers.
8 | // 09/12/14 Naming convention modifications
9 | // 2016/01/30 Replace compare function with the standard CHL_CompareFn type
10 | //
11 |
12 | #ifndef _LINKEDLIST_H
13 | #define _LINKEDLIST_H
14 |
15 | #ifdef __cplusplus
16 | extern "C" {
17 | #endif
18 |
19 | #include "Defines.h"
20 |
21 |
22 | typedef struct _LlNode {
23 | CHL_VAL chlVal;
24 | struct _LlNode *pleft;
25 | struct _LlNode *pright;
26 | }LLNODE, *PLLNODE;
27 |
28 | typedef struct _LinkedList CHL_LLIST, *PCHL_LLIST;
29 | struct _LinkedList {
30 | int nCurNodes;
31 | int nMaxNodes;
32 | CHL_VALTYPE valType;
33 | PLLNODE pHead;
34 | PLLNODE pTail;
35 |
36 | // Access methods
37 |
38 | HRESULT (*Insert)
39 | (
40 | PCHL_LLIST pLList,
41 | PCVOID pvVal,
42 | int iValSize
43 | );
44 |
45 | HRESULT(*Remove)
46 | (
47 | PCHL_LLIST pLList,
48 | PCVOID pvValToFind,
49 | BOOL fStopOnFirstFind,
50 | CHL_CompareFn pfnComparer
51 | );
52 |
53 | HRESULT (*RemoveAt)
54 | (
55 | PCHL_LLIST pLList,
56 | int iIndexToRemove,
57 | PVOID pvValOut,
58 | PINT piValBufSize,
59 | BOOL fGetPointerOnly
60 | );
61 |
62 | HRESULT (*Peek)
63 | (
64 | PCHL_LLIST pLList,
65 | int iIndexToPeek,
66 | PVOID pvValOut,
67 | PINT piValBufSize,
68 | BOOL fGetPointerOnly
69 | );
70 |
71 | HRESULT (*Find)
72 | (
73 | PCHL_LLIST pLList,
74 | PCVOID pvValToFind,
75 | CHL_CompareFn pfnComparer,
76 | PVOID pvValOut,
77 | PINT piValBufSize,
78 | BOOL fGetPointerOnly
79 | );
80 |
81 | HRESULT (*Destroy)(PCHL_LLIST pLList);
82 |
83 | };
84 |
85 | // -------------------------------------------
86 | // Functions exported
87 |
88 | DllExpImp HRESULT CHL_DsCreateLL(_Out_ PCHL_LLIST *ppLList, _In_ CHL_VALTYPE valType, _In_opt_ int nEstEntries);
89 |
90 | // CHL_DsInsertLL()
91 | // Inserts an element into the linked list. Always inserts at the tail.
92 | // Insertion is an O(1) operation.
93 | // pLList: Pointer to a linked list object that was returned by a successful call
94 | // to CHL_DsCreateLL.
95 | // pvVal: The value or pointer to the value to be stored. All primitive types are passed by
96 | // value(like: CHL_DsInsertLL(pListObj, (PVOID)intValue, 0). All other complex
97 | // types are passed by reference(their address) and they are stored in the heap.
98 | // iValSize: Size in bytes of the value. Optional for primitive types, mandatory for others.
99 | //
100 | DllExpImp HRESULT CHL_DsInsertLL
101 | (
102 | _In_ PCHL_LLIST pLList,
103 | _In_ PCVOID pvVal,
104 | _In_opt_ int iValSize
105 | );
106 |
107 | DllExpImp HRESULT CHL_DsRemoveLL
108 | (
109 | _In_ PCHL_LLIST pLList,
110 | _In_ PCVOID pvValToFind,
111 | _In_ BOOL fStopOnFirstFind,
112 | _In_ CHL_CompareFn pfnComparer
113 | );
114 |
115 | DllExpImp HRESULT CHL_DsRemoveAtLL
116 | (
117 | _In_ PCHL_LLIST pLList,
118 | _In_ int iIndexToRemove,
119 | _Inout_opt_ PVOID pvValOut,
120 | _Inout_opt_ PINT piValBufSize,
121 | _In_opt_ BOOL fGetPointerOnly
122 | );
123 |
124 | DllExpImp HRESULT CHL_DsPeekAtLL
125 | (
126 | _In_ PCHL_LLIST pLList,
127 | _In_ int iIndexToPeek,
128 | _Inout_opt_ PVOID pvValOut,
129 | _Inout_opt_ PINT piValBufSize,
130 | _In_opt_ BOOL fGetPointerOnly
131 | );
132 |
133 | DllExpImp HRESULT CHL_DsFindLL
134 | (
135 | _In_ PCHL_LLIST pLList,
136 | _In_ PCVOID pvValToFind,
137 | _In_ CHL_CompareFn pfnComparer,
138 | _Inout_opt_ PVOID pvValOut,
139 | _Inout_opt_ PINT piValBufSize,
140 | _In_opt_ BOOL fGetPointerOnly
141 | );
142 |
143 | DllExpImp HRESULT CHL_DsDestroyLL(_In_ PCHL_LLIST pLList);
144 |
145 | #ifdef __cplusplus
146 | }
147 | #endif
148 |
149 | #endif // _LINKEDLIST_H
150 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | build/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 |
28 | # MSTest test Results
29 | [Tt]est[Rr]esult*/
30 | [Bb]uild[Ll]og.*
31 |
32 | # NUNIT
33 | *.VisualState.xml
34 | TestResult.xml
35 |
36 | # Build Results of an ATL Project
37 | [Dd]ebugPS/
38 | [Rr]eleasePS/
39 | dlldata.c
40 |
41 | # DNX
42 | project.lock.json
43 | artifacts/
44 |
45 | *_i.c
46 | *_p.c
47 | *_i.h
48 | *.ilk
49 | *.meta
50 | *.obj
51 | *.pch
52 | *.pdb
53 | *.pgc
54 | *.pgd
55 | *.rsp
56 | *.sbr
57 | *.tlb
58 | *.tli
59 | *.tlh
60 | *.tmp
61 | *.tmp_proj
62 | *.log
63 | *.vspscc
64 | *.vssscc
65 | .builds
66 | *.pidb
67 | *.svclog
68 | *.scc
69 |
70 | # Chutzpah Test files
71 | _Chutzpah*
72 |
73 | # Visual C++ cache files
74 | ipch/
75 | *.aps
76 | *.ncb
77 | *.opensdf
78 | *.sdf
79 | *.cachefile
80 | *.db
81 |
82 | # Visual Studio profiler
83 | *.psess
84 | *.vsp
85 | *.vspx
86 |
87 | # TFS 2012 Local Workspace
88 | $tf/
89 |
90 | # Guidance Automation Toolkit
91 | *.gpState
92 |
93 | # ReSharper is a .NET coding add-in
94 | _ReSharper*/
95 | *.[Rr]e[Ss]harper
96 | *.DotSettings.user
97 |
98 | # JustCode is a .NET coding add-in
99 | .JustCode
100 |
101 | # TeamCity is a build add-in
102 | _TeamCity*
103 |
104 | # DotCover is a Code Coverage Tool
105 | *.dotCover
106 |
107 | # NCrunch
108 | _NCrunch_*
109 | .*crunch*.local.xml
110 |
111 | # MightyMoose
112 | *.mm.*
113 | AutoTest.Net/
114 |
115 | # Web workbench (sass)
116 | .sass-cache/
117 |
118 | # Installshield output folder
119 | [Ee]xpress/
120 |
121 | # DocProject is a documentation generator add-in
122 | DocProject/buildhelp/
123 | DocProject/Help/*.HxT
124 | DocProject/Help/*.HxC
125 | DocProject/Help/*.hhc
126 | DocProject/Help/*.hhk
127 | DocProject/Help/*.hhp
128 | DocProject/Help/Html2
129 | DocProject/Help/html
130 |
131 | # Click-Once directory
132 | publish/
133 |
134 | # Publish Web Output
135 | *.[Pp]ublish.xml
136 | *.azurePubxml
137 | ## TODO: Comment the next line if you want to checkin your
138 | ## web deploy settings but do note that will include unencrypted
139 | ## passwords
140 | #*.pubxml
141 |
142 | *.publishproj
143 |
144 | # NuGet Packages
145 | *.nupkg
146 | # The packages folder can be ignored because of Package Restore
147 | **/packages/*
148 | # except build/, which is used as an MSBuild target.
149 | !**/packages/build/
150 | # Uncomment if necessary however generally it will be regenerated when needed
151 | #!**/packages/repositories.config
152 |
153 | # Windows Azure Build Output
154 | csx/
155 | *.build.csdef
156 |
157 | # Windows Store app package directory
158 | AppPackages/
159 |
160 | # Visual Studio cache files
161 | # files ending in .cache can be ignored
162 | *.[Cc]ache
163 | # but keep track of directories ending in .cache
164 | !*.[Cc]ache/
165 |
166 | # Others
167 | ClientBin/
168 | [Ss]tyle[Cc]op.*
169 | ~$*
170 | *~
171 | *.dbmdl
172 | *.dbproj.schemaview
173 | *.pfx
174 | *.publishsettings
175 | node_modules/
176 | orleans.codegen.cs
177 |
178 | # RIA/Silverlight projects
179 | Generated_Code/
180 |
181 | # Backup & report files from converting an old project file
182 | # to a newer Visual Studio version. Backup files are not needed,
183 | # because we have git ;-)
184 | _UpgradeReport_Files/
185 | Backup*/
186 | UpgradeLog*.XML
187 | UpgradeLog*.htm
188 |
189 | # SQL Server files
190 | *.mdf
191 | *.ldf
192 |
193 | # Business Intelligence projects
194 | *.rdl.data
195 | *.bim.layout
196 | *.bim_*.settings
197 |
198 | # Microsoft Fakes
199 | FakesAssemblies/
200 |
201 | # Node.js Tools for Visual Studio
202 | .ntvs_analysis.dat
203 |
204 | # Visual Studio 6 build log
205 | *.plg
206 |
207 | # Visual Studio 6 workspace options file
208 | *.opt
209 |
210 | # LightSwitch generated files
211 | GeneratedArtifacts/
212 | _Pvt_Extensions/
213 | ModelManifest.xml
214 |
215 | #Project specific
216 | Debugger/OSD_Log.txt
217 |
--------------------------------------------------------------------------------
/Debugger/Lib/include/Stack.h:
--------------------------------------------------------------------------------
1 |
2 | // Stack.h
3 | // Stack implementation using resizable array
4 | // Shishir Bhat (http://www.shishirbhat.com)
5 | // History
6 | // 2015/12/08 Initial version
7 | //
8 |
9 | #ifndef _CHL_STACK_H
10 | #define _CHL_STACK_H
11 |
12 | #ifdef __cplusplus
13 | extern "C" {
14 | #endif
15 |
16 | #include "Defines.h"
17 | #include "RArray.h"
18 |
19 | typedef struct _stack CHL_STACK, *PCHL_STACK;
20 | struct _stack
21 | {
22 | UINT topIndex;
23 | CHL_RARRAY rarray;
24 |
25 | // Function pointers
26 |
27 | HRESULT (*Create)(_Out_ PCHL_STACK pstk, _In_ CHL_VALTYPE valType, _In_opt_ UINT maxSize);
28 | HRESULT (*Destroy)(_In_ PCHL_STACK pstk);
29 | HRESULT (*Push)(_In_ PCHL_STACK pstk, _In_ PCVOID pVal, _In_opt_ int iBufSize);
30 | HRESULT (*Pop)(_In_ PCHL_STACK pstk, _Out_opt_ PVOID pValBuf, _Inout_opt_ PINT piBufSize);
31 | HRESULT (*Top)(_In_ PCHL_STACK pstk, _Out_opt_ PVOID pValBuf, _Inout_opt_ PINT piBufSize,
32 | _In_ BOOL fGetPointerOnly);
33 | HRESULT (*Peek)(_In_ PCHL_STACK pstk, _In_ UINT index, _Out_opt_ PVOID pValBuf, _Inout_opt_ PINT piBufSize,
34 | _In_ BOOL fGetPointerOnly);
35 | UINT (*Size)(_In_ PCHL_STACK pstk);
36 | };
37 |
38 | // Create a stack for the specified value type and optional max size specification.
39 | // Params:
40 | // pstk : Pointer to a CHL_STACK object that holds the created stack.
41 | // valType : Type of the values in the array. Values of enum CHL_VALTYPE.
42 | // maxSize : Optional. Maximum size the stack can grow to. Default is unlimited.
43 | DllExpImp HRESULT CHL_DsCreateSTK(_Out_ PCHL_STACK pstk, _In_ CHL_VALTYPE valType, _In_opt_ UINT maxSize);
44 |
45 | // Destroy a previously created stack. This frees all memory occupied by any existing stack elements.
46 | // Params:
47 | // pstk : Pointer to a previously created CHL_STACK object
48 | DllExpImp HRESULT CHL_DsDestroySTK(_In_ PCHL_STACK pstk);
49 |
50 | // Push specified value on top of the stack.
51 | // Params:
52 | // pstk : Pointer to a previously created CHL_STACK object
53 | // pVal : Value to be stored. For primitive types, this is the primitive value casted to a PCVOID.
54 | // iBufSize: Size of the value in bytes. For null-terminated strings, zero may be passed.
55 | // Ignored for primitive types.
56 | DllExpImp HRESULT CHL_DsPushSTK(_In_ PCHL_STACK pstk, _In_ PCVOID pVal, _In_opt_ int iBufSize);
57 |
58 | // Pop the value on top of the stack.
59 | // Params:
60 | // pstk : Pointer to a previously created CHL_STACK object
61 | // pValBuf : Optional. Pointer to a buffer to receive the popped value.
62 | // piBufSize : Optional. Pointer to UINT that specifies the provided buffer size.
63 | // If buffer size is insufficient, this argument will contain the required size on return.
64 | DllExpImp HRESULT CHL_DsPopSTK(_In_ PCHL_STACK pstk, _Out_opt_ PVOID pValBuf, _Inout_opt_ PINT piBufSize);
65 |
66 | // Read value at top of stack.
67 | // Params:
68 | // pstk : Pointer to a previously created CHL_STACK object
69 | // pValBuf : Optional. Pointer to a buffer to receive the read value.
70 | // piBufSize : Optional. Pointer to UINT that specifies the provided buffer size.
71 | // If buffer size is insufficient, this argument will contain the required size on return.
72 | // Not required if fGetPointerOnly is TRUE.
73 | // fGetPointerOnly : Retrieve only a pointer to the value at top of stack.
74 | //
75 | DllExpImp HRESULT CHL_DsTopSTK(_In_ PCHL_STACK pstk, _Out_opt_ PVOID pValBuf, _Inout_opt_ PINT piBufSize,
76 | _In_ BOOL fGetPointerOnly);
77 |
78 | // Read value at specified index in the stack.
79 | // Params:
80 | // pstk : Pointer to a previously created CHL_STACK object
81 | // index : Zero-based index. Get the index'th value (top of stack is index 0).
82 | // pValBuf : Optional. Pointer to a buffer to receive the read value.
83 | // piBufSize : Optional. Pointer to UINT that specifies the provided buffer size.
84 | // If buffer size is insufficient, this argument will contain the required size on return.
85 | // Not required if fGetPointerOnly is TRUE.
86 | // fGetPointerOnly : Retrieve only a pointer to the value at top of stack.
87 | DllExpImp HRESULT CHL_DsPeekSTK(_In_ PCHL_STACK pstk, _In_ UINT index, _Out_opt_ PVOID pValBuf, _Inout_opt_ PINT piBufSize,
88 | _In_ BOOL fGetPointerOnly);
89 |
90 | // Get the number of values in the stack currently.
91 | // Params:
92 | // pstk : Pointer to a previously created CHL_STACK object
93 | DllExpImp UINT CHL_DsSizeSTK(_In_ PCHL_STACK pstk);
94 |
95 | #ifdef __cplusplus
96 | }
97 | #endif
98 |
99 | #endif // _CHL_STACK_H
100 |
--------------------------------------------------------------------------------
/Debugger/Lib/include/RArray.h:
--------------------------------------------------------------------------------
1 |
2 | // RArray.h
3 | // Resizable array implementation
4 | // Shishir Bhat (http://www.shishirbhat.com)
5 | // History
6 | // 2015/12/05 Initial version
7 | //
8 |
9 | #ifndef _RARRAY_H
10 | #define _RARRAY_H
11 |
12 | #ifdef __cplusplus
13 | extern "C" {
14 | #endif
15 |
16 | #include "Defines.h"
17 |
18 | // The resizable array object
19 | typedef struct _rarray CHL_RARRAY, *PCHL_RARRAY;
20 | struct _rarray
21 | {
22 | UINT curSize; // Size of array currently
23 | UINT maxSize; // Upper limit for size growth. 0 = unlimited.
24 | CHL_VALTYPE vt; // Value type being held in the array
25 | CHL_VAL *pValArray; // Actual array holding the values
26 |
27 | // Function pointers
28 |
29 | HRESULT (*Create)(_Out_ PCHL_RARRAY pra, _In_ CHL_VALTYPE valType, _In_opt_ UINT initSize, _In_opt_ UINT maxSize);
30 | HRESULT (*Destroy)(_In_ PCHL_RARRAY pra);
31 | HRESULT (*Read)(_In_ PCHL_RARRAY pra, _In_ UINT index, _Out_opt_ PVOID pValBuf,
32 | _Inout_opt_ PINT piBufSize, _In_ BOOL fGetPointerOnly);
33 | HRESULT (*Write)(_In_ PCHL_RARRAY pra, _In_ UINT index, _In_ PCVOID pVal, _In_opt_ int iBufSize);
34 | HRESULT (*ClearAt)(_In_ PCHL_RARRAY pra, _In_ UINT index);
35 | HRESULT (*Resize)(_In_ PCHL_RARRAY pra, _In_ UINT newSize);
36 | UINT (*Size)(_In_ PCHL_RARRAY pra);
37 | UINT (*MaxSize)(_In_ PCHL_RARRAY pra);
38 |
39 | };
40 |
41 | // Create a resizable array for the specified value type and optional size specifications.
42 | // Params:
43 | // pra : Pointer to a CHL_RARRAY object that holds the created resizable array
44 | // valType : Type of the values in the array. Values of enum CHL_VALTYPE.
45 | // initSize : Optional. Initial size of array. Default is 2.
46 | // maxSize : Optional. Maximum size array can grow to. Default is unlimited.
47 | //
48 | DllExpImp HRESULT CHL_DsCreateRA(_Out_ PCHL_RARRAY pra, _In_ CHL_VALTYPE valType, _In_opt_ UINT initSize, _In_opt_ UINT maxSize);
49 |
50 | // Destroy a previously created resizable array. This frees all memory occupied by the underlying array.
51 | // Params:
52 | // pra : Pointer to a previously created CHL_RARRAY object
53 | //
54 | DllExpImp HRESULT CHL_DsDestroyRA(_In_ PCHL_RARRAY pra);
55 |
56 | // Read the value at the specified index and return the value in the specified buffer
57 | // Params:
58 | // pra : Pointer to a previously created CHL_RARRAY object
59 | // index : Array index at which to perform the read. Must be less than the current size of array.
60 | // pValBuf : Optional. Pointer to a buffer to receive the read value.
61 | // piBufSize : Optional. Pointer to UINT that specifies the provided buffer size.
62 | // If buffer size is insufficient, this argument will contain the required size on return.
63 | // Not required if fGetPointerOnly is TRUE.
64 | // fGetPointerOnly : Retrieve only a pointer to the stored array value.
65 | //
66 | DllExpImp HRESULT CHL_DsReadRA(_In_ PCHL_RARRAY pra, _In_ UINT index, _Out_opt_ PVOID pValBuf,
67 | _Inout_opt_ PINT piBufSize, _In_ BOOL fGetPointerOnly);
68 |
69 | // Write to the specified array index, the specified value
70 | // Params:
71 | // pra : Pointer to a previously created CHL_RARRAY object
72 | // index : Array index at which to perform the write. Array is automatically resized if the index is
73 | // greater than the current size of array, up until maxSize is reached (if specified).
74 | // pVal : Value to be stored. For primitive types, this is the primitive value casted to a PCVOID.
75 | // iBufSize : Size of the value in bytes. For null-terminated strings, zero may be passed.
76 | // Ignored for primitive types.
77 | //
78 | DllExpImp HRESULT CHL_DsWriteRA(_In_ PCHL_RARRAY pra, _In_ UINT index, _In_ PCVOID pVal, _In_opt_ int iBufSize);
79 |
80 | // Clear the value stored at the specified index
81 | // Params:
82 | // pra : Pointer to a previously created CHL_RARRAY object
83 | // index : Array index at which to perform the clear. Must be less than the current size of array.
84 | //
85 | DllExpImp HRESULT CHL_DsClearAtRA(_In_ PCHL_RARRAY pra, _In_ UINT index);
86 |
87 | // Force resize of the resizable array to the specified size. New size can be lower or higher than current size.
88 | // Params:
89 | // pra : Pointer to a previously created CHL_RARRAY object
90 | // newSize : Size of the resized array
91 | //
92 | DllExpImp HRESULT CHL_DsResizeRA(_In_ PCHL_RARRAY pra, _In_ UINT newSize);
93 |
94 | // Retrieve current size of the resizable array
95 | // Params:
96 | // pra : Pointer to a previously created CHL_RARRAY object
97 | //
98 | DllExpImp UINT CHL_DsSizeRA(_In_ PCHL_RARRAY pra);
99 |
100 | // Retrieve maximum allowed size of the resizable array. Returns 0 if no limit is set.
101 | // Params:
102 | // pra : Pointer to a previously created CHL_RARRAY object
103 | //
104 | DllExpImp UINT CHL_DsMaxSizeRA(_In_ PCHL_RARRAY pra);
105 |
106 |
107 | #ifdef __cplusplus
108 | }
109 | #endif
110 |
111 | #endif // _RARRAY_H
112 |
--------------------------------------------------------------------------------
/Debugger/Logger.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Inc\Logger.h"
3 |
4 | #define MAX_LOGLINE (SLEN_LOGLINE + 24) // accounting for the extra time info length and logtype
5 |
6 | static void vWriteLogInternal(int iLogType, LOGGER *pLogger, const WCHAR* pszMessage, int nLen);
7 |
8 | BOOL fInitializeLogger(WCHAR *pszLogFilepath, __out LOGGER *pLogger)
9 | {
10 | HANDLE hMutex = NULL;
11 | WCHAR szMutexNameTemp[SLEN_COMMON64];
12 |
13 | HANDLE hFile = NULL;
14 |
15 | ASSERT(pszLogFilepath);
16 | ASSERT(pLogger);
17 |
18 | // todo: check return value
19 | LoadString(GetModuleHandle(NULL), IDS_LOGGERMUTEX, szMutexNameTemp, _countof(szMutexNameTemp) - SLEN_INT16);
20 |
21 | memset(pLogger, 0, sizeof(LOGGER));
22 |
23 | srand(time(NULL));
24 | swprintf_s(pLogger->szMutexName, _countof(pLogger->szMutexName), L"%s_%d", szMutexNameTemp, rand() % 65536);
25 | if(!(hMutex = CreateMutex(NULL, true, pLogger->szMutexName)))
26 | {
27 | // todo: do something similar to throw exception
28 | goto error_return;
29 | }
30 |
31 | // Create log file
32 | hFile = CreateFile(pszLogFilepath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
33 | if(hFile == NULL)
34 | {
35 | // todo: do something similar to throw exception
36 | goto error_return;
37 | }
38 |
39 | pLogger->hMutex = hMutex;
40 | pLogger->hLogFile = hFile;
41 |
42 | ReleaseMutex(hMutex);
43 | vWriteLog(pLogger, L"Logger Initialized");
44 | return TRUE;
45 |
46 | error_return:
47 | if(hFile)
48 | {
49 | CloseHandle(hFile);
50 | }
51 |
52 | if(hMutex)
53 | {
54 | ReleaseMutex(hMutex);
55 | CloseHandle(hMutex);
56 | }
57 |
58 | memset(pLogger, 0, sizeof(LOGGER));
59 | return FALSE;
60 | }
61 |
62 | void vTerminateLogger(LOGGER *pLogger)
63 | {
64 | ASSERT(pLogger);
65 | ASSERT(pLogger->hMutex);
66 | ASSERT(pLogger->hLogFile);
67 |
68 | if(WaitForSingleObject(pLogger->hMutex, INFINITE) != WAIT_OBJECT_0)
69 | {
70 | // todo: something like an exception. SEH?
71 | return;
72 | }
73 | vWriteLog(pLogger, L"Logger Terminating...");
74 | CloseHandle(pLogger->hLogFile);
75 | CloseHandle(pLogger->hMutex);
76 |
77 | // Mutex is never released
78 |
79 | memset(pLogger, 0, sizeof(LOGGER));
80 | return;
81 | }
82 |
83 | // Writes a line of log to the logger. Uses LOGTYPE_TRACE to log the line.
84 | //
85 | void vWriteLog(LOGGER *pLogger, const WCHAR* pszMessageFmt, ...)
86 | {
87 | ASSERT(pszMessageFmt);
88 |
89 | va_list pArgs;
90 | WCHAR szLogMessage[SLEN_LOGLINE];
91 |
92 | HRESULT hrReturn = S_OK;
93 |
94 | va_start(pArgs, pszMessageFmt);
95 | hrReturn = StringCchVPrintf(szLogMessage, _countof(szLogMessage), pszMessageFmt, pArgs);
96 | va_end(pArgs);
97 |
98 | if(FAILED(hrReturn))
99 | {
100 | // todo:
101 | return;
102 | }
103 |
104 | vWriteLogInternal(LOGTYPE_TRACE, pLogger, szLogMessage, wcslen(szLogMessage));
105 | return;
106 | }
107 |
108 | // Function that allows one to specify the log type to be written.
109 | // TRACE, WARN or ERROR types. The corresponding string will be appended to the
110 | // beginning of the log line.
111 | // ** Added a new function instead of changing the vWriteLog() to prevent breaking
112 | // ** existing callers.
113 | void vWriteLogType(int iLogLevel, PLOGGER pLogger, const WCHAR *pszMessageFmt, ...)
114 | {
115 | ASSERT(pszMessageFmt);
116 | ASSERT(iLogLevel >= LOGTYPE_TRACE && iLogLevel <= LOGTYPE_ERROR);
117 |
118 | va_list pArgs;
119 | WCHAR szLogMessage[SLEN_LOGLINE];
120 |
121 | HRESULT hrReturn = S_OK;
122 |
123 | va_start(pArgs, pszMessageFmt);
124 | hrReturn = StringCchVPrintf(szLogMessage, _countof(szLogMessage), pszMessageFmt, pArgs);
125 | va_end(pArgs);
126 |
127 | if(FAILED(hrReturn))
128 | {
129 | // todo:
130 | return;
131 | }
132 |
133 | vWriteLogInternal(iLogLevel, pLogger, szLogMessage, wcslen(szLogMessage));
134 | }
135 |
136 | // Internal function that actually does the writing to log file part
137 | //
138 | static void vWriteLogInternal(int iLogLevel, LOGGER *pLogger, const WCHAR* pszMessage, int nLen)
139 | {
140 | ASSERT(pLogger);
141 | ASSERT(pszMessage);
142 | ASSERT(nLen > 1);
143 |
144 | SYSTEMTIME stCurrentTime;
145 | WCHAR szLogMessage[MAX_LOGLINE];
146 |
147 | DWORD dwLogChars;
148 | DWORD dwWritten;
149 |
150 | GetLocalTime(&stCurrentTime);
151 |
152 | // todo: read only nLen chars from pszMessage
153 |
154 | // Construct the string to be displayed
155 | switch(iLogLevel)
156 | {
157 | case LOGTYPE_TRACE:
158 | {
159 | swprintf_s(szLogMessage, MAX_LOGLINE, L"[%02d:%02d:%02d.%03d] TRACE: %s\r\n", stCurrentTime.wHour,
160 | stCurrentTime.wMinute, stCurrentTime.wSecond, stCurrentTime.wMilliseconds, pszMessage);
161 | break;
162 | }
163 |
164 | case LOGTYPE_WARN:
165 | {
166 | swprintf_s(szLogMessage, MAX_LOGLINE, L"[%02d:%02d:%02d.%03d] WARN : %s\r\n", stCurrentTime.wHour,
167 | stCurrentTime.wMinute, stCurrentTime.wSecond, stCurrentTime.wMilliseconds, pszMessage);
168 | break;
169 | }
170 |
171 | case LOGTYPE_ERROR:
172 | {
173 | swprintf_s(szLogMessage, MAX_LOGLINE, L"[%02d:%02d:%02d.%03d] ERROR: %s\r\n", stCurrentTime.wHour,
174 | stCurrentTime.wMinute, stCurrentTime.wSecond, stCurrentTime.wMilliseconds, pszMessage);
175 | break;
176 | }
177 |
178 | default:
179 | ASSERT(FALSE);
180 | break;
181 | }
182 |
183 | ASSERT(pLogger->hLogFile);
184 | ASSERT(pLogger->hMutex);
185 |
186 | // Get mutex
187 | if(WaitForSingleObject(pLogger->hMutex, INFINITE) != WAIT_OBJECT_0)
188 | {
189 | // todo: something like an exception. SEH?
190 | return;
191 | }
192 |
193 | dwLogChars = wcslen(szLogMessage) * sizeof(WCHAR);
194 | if(!WriteFile(pLogger->hLogFile, szLogMessage, dwLogChars, &dwWritten, NULL))
195 | {
196 | // todo: SEH?
197 | }
198 | else if(dwWritten != dwLogChars)
199 | {
200 | // todo: SEH?
201 | }
202 |
203 | ReleaseMutex(pLogger->hMutex);
204 | return;
205 | }
206 |
--------------------------------------------------------------------------------
/Debugger/Dasm/Utils.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Utils.h"
3 | #include "Defines.h"
4 |
5 | /* Util_fSplitModRMByte()
6 | * Given the ModR/M byte value, returns the individual fields:
7 | * Mod, Reg/Opcode and R/M via pointers to byte variables.
8 | * If any of the __out pointers are NULL, then those fields
9 | * are not computed.
10 | *
11 | * **** This function is also used to spli the SIB byte ****
12 | * ModRM and SIB have the same structure!
13 | *
14 | * Args:
15 | * bModRMValue: BYTE: value of the ModR/M byte.
16 | * pbMod: PBYTE: Address in which to store the Mod field value.
17 | * pbReg: PBYTE: Address in which to store the Reg/Opcode field value.
18 | * pbRM: PBYTE: Address in which to store the R/M field value.
19 | *
20 | * RetVal:
21 | * none
22 | */
23 | void Util_vSplitModRMByte(BYTE bModRMValue, __out PBYTE pbMod,
24 | __out PBYTE pbReg, __out PBYTE pbRM)
25 | {
26 | // Bits: 7 6 5 4 3 2 1 0
27 | // Field: Mod Reg R/M
28 | if(pbMod)
29 | *pbMod = (bModRMValue & MOD_MASK) >> 6;
30 | if(pbReg)
31 | *pbReg = (bModRMValue & REG_MASK) >> 3;
32 | if(pbRM)
33 | *pbRM = bModRMValue & RM_MASK;
34 |
35 | return;
36 |
37 | }// Util_fSplitModRMByte
38 |
39 |
40 | /* Util_vGetDWBits()
41 | * Given the opcode byte, returns the value of the d and w bits
42 | * of the opcode. If any of the __out pointers are NULL, then
43 | * those fields are not computed.
44 | *
45 | * Args:
46 | * bOpcode: BYTE: value of the opcode byte.
47 | * pbDBit: PBYTE: Address in which to store the D-bit value.
48 | * pbWBit: PBYTE: Address in which to store the W-bit value.
49 | *
50 | * RetVal:
51 | * none
52 | */
53 | void Util_vGetDWBits(BYTE bOpcode, __out PBYTE pbDBit, __out PBYTE pbWBit)
54 | {
55 |
56 | if(pbDBit)
57 | *pbDBit = (bOpcode & DBIT_MASK) >> 1;
58 | if(pbWBit)
59 | *pbWBit = bOpcode & WBIT_MASK;
60 |
61 | return;
62 |
63 | }// Util_vGetDWBits()
64 |
65 |
66 | /* Util_fIsPrefix()
67 | * Given a byte as argument, tells whether it is a valid prefix or not.
68 | *
69 | * Args:
70 | * bValue: BYTE: value to be checked.
71 | *
72 | * RetVal:
73 | * TRUE/FALSE depending on whether bValue is a prefix or not.
74 | */
75 | BOOL Util_fIsPrefix(BYTE bValue)
76 | {
77 | switch(bValue)
78 | {
79 | case OPC_PREFIX_SEGOVR_ES:
80 | case OPC_PREFIX_SEGOVR_CS:
81 | case OPC_PREFIX_SEGOVR_SS:
82 | case OPC_PREFIX_SEGOVR_DS:
83 | case OPC_PREFIX_SEGOVR_FS:
84 | case OPC_PREFIX_SEGOVR_GS:
85 | case OPC_PREFIX_OPSIZE:
86 | case OPC_PREFIX_ADSIZE:
87 | case OPC_PREFIX_LOCK:
88 | case OPC_PREFIX_REPNE:
89 | case OPC_PREFIX_REPE:
90 | {
91 | return TRUE;
92 | }
93 | default:
94 | break;
95 | }// switch(bValue)
96 |
97 | return FALSE;
98 |
99 | }// Util_fIsPrefix()
100 |
101 |
102 | // Notes: Under construction
103 | BOOL Util_fDumpIMAGE_IMPORT_DESCRIPTORS(DWORD rva, DWORD dwSize,
104 | PIMAGE_NT_HEADERS pNTHeaders, DWORD dwFileBase)
105 | {
106 |
107 | PIMAGE_SECTION_HEADER pImgSecHeader = NULL;
108 | PIMAGE_IMPORT_DESCRIPTOR pImports = NULL;
109 |
110 | INT iFilePtrRVADelta = 0;
111 |
112 | WCHAR wszTimeStamp[32];
113 |
114 | // First get the file pointer of the first IMAGE_IMPORT_DESCRIPTOR
115 | if( !CHL_PsGetEnclosingSectionHeader(rva, pNTHeaders, &pImgSecHeader))
116 | {
117 | wprintf_s(L"fDumpIMAGE_IMPORT_DESCRIPTOR(): Unable to retrieve section header\n");
118 | wprintf_s(L"rva = 0x%xh, dwSize = 0x%xh, pNTHeaders = %p, dwFileBase = 0x%08xh\n",
119 | rva, dwSize, pNTHeaders, dwFileBase);
120 | return FALSE;
121 | }
122 |
123 | iFilePtrRVADelta = (INT)(pImgSecHeader->PointerToRawData - pImgSecHeader->VirtualAddress);
124 |
125 | // find the Imports within the section
126 | pImports = (PIMAGE_IMPORT_DESCRIPTOR)(rva + iFilePtrRVADelta + dwFileBase);
127 |
128 | wprintf_s(L"\n** IMAGE_IMPORT_DESCRIPTOR **\n");
129 |
130 | while(pImports->Characteristics != 0 || pImports->FirstThunk != 0 ||
131 | pImports->ForwarderChain != 0 || pImports->Name != 0 ||
132 | pImports->OriginalFirstThunk != 0 || pImports->TimeDateStamp != 0)
133 | {
134 | wprintf_s(L"Entry:\n");
135 | wprintf_s(L" Char/OrigFirstThunk: %x\n", pImports->OriginalFirstThunk);
136 | if( pImports->TimeDateStamp != 0 &&
137 | _wctime_s(wszTimeStamp, _countof(wszTimeStamp), (time_t*)&pImports->TimeDateStamp)
138 | == 0 )
139 | {
140 | wprintf_s(L" TimeDateStamp: %xh %s\n", pImports->TimeDateStamp, wszTimeStamp);
141 | }
142 | wprintf_s(L" ForwarderChain: %xh\n", pImports->ForwarderChain);
143 | if(pImports->Name)
144 | wprintf_s(L" Name: %S\n", pImports->Name + iFilePtrRVADelta + dwFileBase);
145 | wprintf_s(L" FirstThunk: %xh\n", pImports->FirstThunk);
146 | wprintf_s(L" IAT:\n");
147 |
148 | PIMAGE_THUNK_DATA pImgThunkData = (PIMAGE_THUNK_DATA)(pImports->FirstThunk + iFilePtrRVADelta + dwFileBase);
149 |
150 | // Dump the IAT
151 | {
152 | while(pImgThunkData->u1.AddressOfData != 0)
153 | {
154 | wprintf_s(L" -> ");
155 | // If the high bit is set, the bottom 31bits is
156 | // treated as the ordinal value
157 | if(pImgThunkData->u1.AddressOfData & 0x80000000)
158 | wprintf_s(L"Ordinal: %08x\n", IMAGE_ORDINAL(pImgThunkData->u1.Ordinal));
159 | else
160 | // IMAGE_THUNK_ DATA value is an RVA to the IMAGE_IMPORT_BY_NAME
161 | {
162 | PIMAGE_IMPORT_BY_NAME pImpByName = (PIMAGE_IMPORT_BY_NAME)(pImgThunkData->u1.AddressOfData +
163 | iFilePtrRVADelta + dwFileBase);
164 | wprintf_s(L"Hint: %4u Name: %S\n", pImpByName->Hint, pImpByName->Name);
165 | }
166 |
167 | ++pImgThunkData;
168 |
169 | }// while(pImgThunkData->u1 != 0)
170 | }// IAT block
171 |
172 | wprintf_s(L"\n");
173 |
174 | ++pImports;// += sizeof(IMAGE_IMPORT_DESCRIPTOR);
175 |
176 | }
177 |
178 | return TRUE;
179 | }
180 |
181 |
182 | void Util_vTwosComplementByte(BYTE chSignedVal, __out PBYTE pchOut)
183 | {
184 | __asm {
185 | push eax
186 | push ebx
187 | xor eax,eax
188 | mov al, chSignedVal
189 | not al
190 | add al, 1
191 | mov ebx, pchOut
192 | mov byte ptr [ebx], al
193 | pop ebx
194 | pop eax
195 | }
196 |
197 | return;
198 | }
199 |
200 |
201 | void Util_vTwosComplementInt(INT iSignedVal, __out PINT piOut)
202 | {
203 | __asm {
204 | push eax
205 | push ebx
206 | xor eax,eax
207 | mov eax, iSignedVal
208 | not eax
209 | add eax, 1
210 | mov ebx, piOut
211 | mov dword ptr [ebx], eax
212 | pop ebx
213 | pop eax
214 | }
215 |
216 | return;
217 | }
218 |
--------------------------------------------------------------------------------
/Debugger/Debugger.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 | {79ad6207-93cc-4ac7-a504-441fca4b2536}
18 |
19 |
20 | {144a647b-00a8-4705-9a44-15b370cb2dbf}
21 |
22 |
23 | {9ccf8d90-3882-4189-a103-4d16307fba65}
24 |
25 |
26 |
27 |
28 | Source Files
29 |
30 |
31 | Source Files
32 |
33 |
34 | Source Files
35 |
36 |
37 | Source Files
38 |
39 |
40 | Source Files
41 |
42 |
43 | Source Files
44 |
45 |
46 | Source Files
47 |
48 |
49 | Source Files
50 |
51 |
52 | Source Files
53 |
54 |
55 | Source Files
56 |
57 |
58 | Source Files
59 |
60 |
61 | Source Files
62 |
63 |
64 | Dasm
65 |
66 |
67 | Dasm
68 |
69 |
70 | Dasm
71 |
72 |
73 |
74 |
75 | Header Files
76 |
77 |
78 | Header Files
79 |
80 |
81 | Header Files
82 |
83 |
84 | Header Files
85 |
86 |
87 | Header Files
88 |
89 |
90 | Header Files
91 |
92 |
93 | Header Files
94 |
95 |
96 | Header Files
97 |
98 |
99 | Header Files
100 |
101 |
102 | Header Files
103 |
104 |
105 | Header Files
106 |
107 |
108 | Header Files
109 |
110 |
111 | Header Files
112 |
113 |
114 | Header Files
115 |
116 |
117 | Header Files
118 |
119 |
120 | Header Files
121 |
122 |
123 | Header Files
124 |
125 |
126 | Header Files
127 |
128 |
129 | Dasm\Header Files
130 |
131 |
132 | Dasm\Header Files
133 |
134 |
135 | Dasm\Header Files
136 |
137 |
138 | Dasm\Header Files
139 |
140 |
141 | Header Files
142 |
143 |
144 | Header Files
145 |
146 |
147 | Libs
148 |
149 |
150 | Libs
151 |
152 |
153 | Libs
154 |
155 |
156 | Libs
157 |
158 |
159 | Libs
160 |
161 |
162 | Libs
163 |
164 |
165 | Libs
166 |
167 |
168 | Libs
169 |
170 |
171 | Libs
172 |
173 |
174 | Libs
175 |
176 |
177 | Libs
178 |
179 |
180 | Libs
181 |
182 |
183 | Libs
184 |
185 |
186 | Libs
187 |
188 |
189 | Libs
190 |
191 |
192 | Libs
193 |
194 |
195 | Libs
196 |
197 |
198 | Libs
199 |
200 |
201 |
202 |
203 | Resource Files
204 |
205 |
206 |
--------------------------------------------------------------------------------
/Debugger/Lib/include/Hashtable.h:
--------------------------------------------------------------------------------
1 |
2 | // Hashtable.h
3 | // Hashtable implementation with buckets
4 | // Shishir Bhat (http://www.shishirbhat.com)
5 | // History
6 | // Unknown history!
7 | // 09/09/14 Refactor to store defs in individual headers.
8 | // 09/12/14 Naming convention modifications
9 | //
10 |
11 | #ifndef _HASHTABLE_H
12 | #define _HASHTABLE_H
13 |
14 | #ifdef __cplusplus
15 | extern "C" {
16 | #endif
17 |
18 | #include "Defines.h"
19 | #include "MemFunctions.h"
20 |
21 | // hashtable node
22 | typedef struct _hashTableNode {
23 | BOOL fOccupied;
24 | CHL_KEY chlKey;
25 | CHL_VAL chlVal;
26 | struct _hashTableNode *pnext;
27 | }HT_NODE;
28 |
29 | // Foward declare the iterator struct
30 | struct _hashtableIterator;
31 |
32 | // hashtable itself
33 | typedef struct _hashtable CHL_HTABLE, *PCHL_HTABLE;
34 | struct _hashtable {
35 | CHL_KEYTYPE keyType; // Type information for the hashtable key
36 | CHL_VALTYPE valType; // Type information for the hashtable value
37 | BOOL fValIsInHeap; // Whether value was allocated on heap by client (for CHL_VT_POINTER only)
38 | HT_NODE *phtNodes; // Pointer to hashtable nodes
39 | int nTableSize; // Total number of buckets in the hashtable
40 |
41 | // Access methods
42 | HRESULT (*Destroy)(PCHL_HTABLE phtable);
43 |
44 | HRESULT (*Insert)(
45 | PCHL_HTABLE phtable,
46 | PCVOID pvkey,
47 | int iKeySize,
48 | PVOID pvVal,
49 | int iValSize);
50 |
51 | HRESULT (*Find)(
52 | PCHL_HTABLE phtable,
53 | PCVOID pvkey,
54 | int iKeySize,
55 | PVOID pvVal,
56 | PINT pvalsize,
57 | BOOL fGetPointerOnly);
58 |
59 | HRESULT (*Remove)(PCHL_HTABLE phtable, PCVOID pvkey, int iKeySize);
60 |
61 | HRESULT (*InitIterator)(PCHL_HTABLE phtable, struct _hashtableIterator *pItr);
62 | HRESULT (*GetNext)(
63 | struct _hashtableIterator *pItr,
64 | PCVOID pvKey,
65 | PINT pkeysize,
66 | PVOID pvVal,
67 | PINT pvalsize,
68 | BOOL fGetPointerOnly);
69 |
70 | void (*Dump)(PCHL_HTABLE phtable);
71 | };
72 |
73 | // Structure that defines the iterator for the hashtable
74 | // Callers can use this to iterate through the hashtable
75 | // and get all (key,value) pairs one-by-one
76 | typedef struct _hashtableIterator {
77 | int opType;
78 | int nCurIndex; // current position in the main bucket
79 | HT_NODE *phtCurNodeInList; // current position in the sibling list
80 | PCHL_HTABLE pMyHashTable; // Pointer to the hashtable to work on
81 | }CHL_HT_ITERATOR;
82 |
83 | // -------------------------------------------
84 | // Functions exported
85 |
86 | // Creates a hashtable and returns a pointer which can be used for later operations
87 | // on the table.
88 | // Params:
89 | // pHTableOut: Address of pointer where to copy the pointer to the hashtable
90 | // nEstEntries: Estimated number of entries that would be in the table at any given time.
91 | // This is used to determine the initial size of the hashtable.
92 | // keyType: Type of variable that is used as key - a string or a number
93 | // valType: Type of value that is stored - number, string or void(can be anything)
94 | // fValInHeapMem: Set this to true if the value(type is CHL_VT_POINTER) is allocated memory on the heap.
95 | // This indicates the hash table to free it when a table entry is removed.
96 | //
97 | DllExpImp HRESULT CHL_DsCreateHT(
98 | _Inout_ CHL_HTABLE **pHTableOut,
99 | _In_ int nEstEntries,
100 | _In_ CHL_KEYTYPE keyType,
101 | _In_ CHL_VALTYPE valType,
102 | _In_opt_ BOOL fValInHeapMem);
103 |
104 | // Destroy the hashtable by removing all key-value pairs from the hashtable.
105 | // The CHL_HTABLE object itself is also destroyed.
106 | // Params:
107 | // phtable: Pointer to the hashtable object returned by CHL_DsCreateHT function.
108 | //
109 | DllExpImp HRESULT CHL_DsDestroyHT(_In_ CHL_HTABLE *phtable);
110 |
111 | // Inserts a key,value pair into the hash table. If the key already exists, then the value is over-written
112 | // with the new value. If both the key and value already exist, then nothing is changed in the hash table.
113 | // Params:
114 | // phtable: Pointer to the hashtable object returned by CHL_DsCreateHT function.
115 | // pvkey: Pointer to the key. For primitive types, this is the primitive value casted to a PCVOID.
116 | // iKeySize: Size of the key in bytes. For null-terminated strings, zero may be passed.
117 | // pvVal: Value to be stored. Please see documentation for details.
118 | // iValSize: Size of the value in bytes. For null-terminated strings, zero may be passed.
119 | //
120 | DllExpImp HRESULT CHL_DsInsertHT(
121 | _In_ CHL_HTABLE *phtable,
122 | _In_ PCVOID pvkey,
123 | _In_ int iKeySize,
124 | _In_ PCVOID pvVal,
125 | _In_ int iValSize);
126 |
127 | // Find the specified key in the hash table.
128 | // Params:
129 | // phtable: Pointer to the hashtable object returned by CHL_DsCreateHT function.
130 | // pvkey: Pointer to the key. For primitive types, this is the primitive value casted to a PCVOID.
131 | // iKeySize: Size of the key in bytes. For null-terminated strings, zero may be passed.
132 | // pvVal: Optional. Pointer to a buffer to receive the value, if found.
133 | // pvalsize: Optional. Size of the value buffer in bytes. If specified size is insufficient, the function
134 | // returns the required size back in this parameter.
135 | // fGetPointerOnly: Applies to value of type CHL_VT_USEROBJECT/CHL_VT_STRING/CHL_VT_WSTRING -
136 | // If this is TRUE, function returns a pointer to the stored value in the buffer pvVal.
137 | // Otherwise, the full value is copied into the pvVal buffer.
138 | //
139 | DllExpImp HRESULT CHL_DsFindHT(
140 | _In_ CHL_HTABLE *phtable,
141 | _In_ PCVOID pvkey,
142 | _In_ int iKeySize,
143 | _Inout_opt_ PVOID pvVal,
144 | _Inout_opt_ PINT pvalsize,
145 | _In_opt_ BOOL fGetPointerOnly);
146 |
147 | // Deletes the specified key from the hash table.
148 | // Params:
149 | // phtable: Pointer to the hashtable object returned by CHL_DsCreateHT function.
150 | // pvkey: Pointer to the key. For primitive types, this is the primitive value casted to a PCVOID.
151 | // iKeySize: Size of the key in bytes. For null-terminated strings, zero may be passed.
152 | //
153 | DllExpImp HRESULT CHL_DsRemoveHT(_In_ CHL_HTABLE *phtable, _In_ PCVOID pvkey, _In_ int iKeySize);
154 |
155 | // Initialize the iterator object for use with the specified hashtable.
156 | // Params:
157 | // pItr: Pointer to the iterator object to initialize.
158 | // phtable: Pointer to the hashtable object returned by CHL_DsCreateHT function.
159 | //
160 | DllExpImp HRESULT CHL_DsInitIteratorHT(_In_ PCHL_HTABLE phtable, _Inout_ CHL_HT_ITERATOR *pItr);
161 |
162 | // Get the next element in the hash table using the specified iterator object.
163 | // Params:
164 | // pItr: The iterator object that was initialized by CHL_DsInitIteratorHT.
165 | // pvKey: Optional. Pointer to buffer to receive the key of the next item.
166 | // pKeySize: Optional. Size of the key buffer in bytes. If specified size is insufficient, the function
167 | // returns the required size back in this parameter.
168 | // pvVal: Refer documentation of the CHL_DsFindHT() function.
169 | // pvalsize: Refer documentation of the CHL_DsFindHT() function.
170 | // fGetPointerOnly: Refer documentation of the CHL_DsFindHT() function.
171 | //
172 | DllExpImp HRESULT CHL_DsGetNextHT(
173 | _In_ CHL_HT_ITERATOR *pItr,
174 | _Inout_opt_ PCVOID pvKey,
175 | _Inout_opt_ PINT pkeysize,
176 | _Inout_opt_ PVOID pvVal,
177 | _Inout_opt_ PINT pvalsize,
178 | _In_opt_ BOOL fGetPointerOnly);
179 |
180 | DllExpImp int CHL_DsGetNearestSizeIndexHT(_In_ int maxNumberOfEntries);
181 | DllExpImp void CHL_DsDumpHT(_In_ CHL_HTABLE *phtable);
182 |
183 | // Exposing for unit testing
184 | DllExpImp DWORD _GetKeyHash(_In_ PVOID pvKey, _In_ CHL_KEYTYPE keyType, _In_ int iKeySize, _In_ int iTableNodes);
185 |
186 | #ifdef __cplusplus
187 | }
188 | #endif
189 |
190 | #endif // _HASHTABLE_H
191 |
--------------------------------------------------------------------------------
/Debugger/Debugger.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | {EDEFC84A-1AD6-4FA6-8042-E198F3172866}
15 | Win32Proj
16 | Debugger
17 | 10.0.15063.0
18 |
19 |
20 |
21 | Application
22 | true
23 | Unicode
24 | v141
25 |
26 |
27 | Application
28 | false
29 | true
30 | Unicode
31 | v141
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | true
45 | $(VC_IncludePath);$(UniversalCRT_IncludePath);$(WindowsSDK_IncludePath);Lib\include
46 |
47 |
48 | false
49 | $(VC_IncludePath);$(UniversalCRT_IncludePath);$(WindowsSDK_IncludePath);Lib\include
50 |
51 |
52 |
53 | NotUsing
54 | Level4
55 | Disabled
56 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)
57 | Lib\$(Configuration)\
58 | false
59 |
60 |
61 | Windows
62 | true
63 | false
64 | true
65 | Lib\$(Configuration)\
66 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Comctl32.lib;Psapi.lib;CHelpLib.lib;%(AdditionalDependencies)
67 |
68 |
69 | xcopy /y $(ProjectDir)Lib\$(Configuration)\CHelpLib.dll $(OutDir)
70 | Copy external DLL to output folder
71 |
72 |
73 |
74 |
75 | Level3
76 | NotUsing
77 | MaxSpeed
78 | true
79 | true
80 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
81 | Lib\$(Configuration)\
82 |
83 |
84 | Windows
85 | false
86 | true
87 | true
88 | false
89 | Lib\$(Configuration)\
90 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Comctl32.lib;Psapi.lib;CHelpLib.lib;%(AdditionalDependencies)
91 |
92 |
93 | xcopy /y $(ProjectDir)Lib\$(Configuration)\CHelpLib.dll $(OutDir)
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/Debugger/Breakpoint.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Inc\Breakpoint.h"
3 |
4 | extern PLOGGER pstLogger;
5 |
6 | #define OPCODE_BREAKPOINT 0xCC
7 |
8 | static int iGetFirstFreeIdentifier(PINT paiIdentifiers);
9 | static BOOL fBpInsert_Internal(HANDLE hTargetProcess, DWORD dwTargetAddr, __out PBYTE pbOrigCodeByte);
10 | static BOOL fBpRemove_Internal(HANDLE hTargetProcess, DWORD dwTargetAddr, BYTE bOrigCodeByte);
11 | static BOOL fBpCompare(PVOID pvLeft, PVOID pvRight);
12 |
13 | // ** Function Definitions **
14 | BOOL fBpInitialize(__out PBPLIST *ppstBpList)
15 | {
16 | ASSERT(ppstBpList);
17 |
18 | DWORD dwErrorCode = ERROR_SUCCESS;
19 | PBPLIST pstBpList = NULL;
20 |
21 | if(FAILED(CHL_MmAlloc((void**)&pstBpList, sizeof(BPLIST), &dwErrorCode)))
22 | {
23 | logerror(pstLogger, L"%s(): CHL_MmAlloc() failed %u", __FUNCTIONW__, GetLastError());
24 | return FALSE;
25 | }
26 |
27 | // pstBpList->aiIdentifiers[] will be zero filled
28 |
29 | if(FAILED(CHL_DsCreateLL(&pstBpList->pstLinkedListBp, CHL_VT_POINTER, MAX_BREAKPOINTS)))
30 | {
31 | logerror(pstLogger, L"%s(): CHL_DsCreateLL() failed %u", __FUNCTIONW__, GetLastError());
32 | CHL_MmFree((void**)&pstBpList);
33 | return FALSE;
34 | }
35 |
36 | *ppstBpList = pstBpList;
37 | return TRUE;
38 | }
39 |
40 | BOOL fBpTerminate(PBPLIST pBreakpoints)
41 | {
42 | ASSERT(pBreakpoints);
43 | ASSERT(pBreakpoints->pstLinkedListBp);
44 |
45 | BOOL fRetVal = CHL_DsDestroyLL(pBreakpoints->pstLinkedListBp);
46 |
47 | CHL_MmFree((void**)&pBreakpoints);
48 |
49 | return fRetVal;
50 | }
51 |
52 | BOOL fBpInsert(PBPLIST pstBpList, PBPINFO pstBpInfo, PTARGETINFO pstTargetInfo, __out OPTIONAL PINT piBpID)
53 | {
54 | ASSERT(pstBpList);
55 | ASSERT(pstBpInfo);
56 | ASSERT(pstTargetInfo);
57 |
58 | BREAKPOINT stBreakpoint;
59 | int id;
60 |
61 | id = iGetFirstFreeIdentifier(pstBpList->aiIdentifiers);
62 |
63 | // Assume 1-1 mapping between logical and actual breakpoint for now
64 | // TODO: implement n-1 mapping
65 |
66 | stBreakpoint.id = id;
67 | stBreakpoint.bpType = pstBpInfo->iBpType;
68 |
69 | if(pstBpInfo->iBpType & BPTYPE_ASMLEVEL)
70 | {
71 | stBreakpoint.stActualBp.dwAddrInTarget = pstBpInfo->dwTargetAddr;
72 | }
73 | else
74 | {
75 | // TODO: support this
76 | SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
77 | goto error_return;
78 | }
79 |
80 | stBreakpoint.nReferences = 1;
81 |
82 | // Insert breakpoint into target process
83 | if(!fBpInsert_Internal(
84 | pstTargetInfo->stProcessInfo.hProcess,
85 | pstBpInfo->dwTargetAddr,
86 | &stBreakpoint.stActualBp.bOrigCodeByte))
87 | {
88 | goto error_return;
89 | }
90 |
91 | stBreakpoint.stActualBp.fResolved = TRUE;
92 |
93 | // Insert into list of breakpoints
94 | if(FAILED(CHL_DsInsertLL(pstBpList->pstLinkedListBp, &stBreakpoint, sizeof(stBreakpoint))))
95 | {
96 | logerror(pstLogger, L"%s(): CHL_DsInsertLL() failed %u", __FUNCTIONW__, GetLastError());
97 |
98 | // Remove the inserted breakpoint
99 | if(stBreakpoint.nReferences == 1)
100 | {
101 | fBpRemove_Internal(pstTargetInfo->stProcessInfo.hProcess, pstBpInfo->dwTargetAddr, stBreakpoint.stActualBp.bOrigCodeByte);
102 | }
103 |
104 | goto error_return;
105 | }
106 |
107 | IFPTR_SETVAL(piBpID, id);
108 | return TRUE;
109 |
110 | error_return:
111 | return FALSE;
112 | }
113 |
114 | BOOL fBpRemove(PBPLIST pstBpList, PBPINFO pstBpInfo, PTARGETINFO pstTargetInfo)
115 | {
116 | ASSERT(pstBpList);
117 | ASSERT(pstBpInfo);
118 |
119 | // Assume 1-1 mapping between logical and actual breakpoint for now
120 | // TODO: implement n-1 mapping
121 |
122 | // Only ASM level breakpoints now
123 | // TODO: SOURCE level and using the identifier
124 |
125 | BREAKPOINT stBpToFind;
126 | PBREAKPOINT pstBpFound;
127 |
128 | // TODO: assign bpType as well
129 | stBpToFind.stActualBp.dwAddrInTarget = pstBpInfo->dwTargetAddr;
130 |
131 | int cbOut = sizeof(pstBpFound);
132 | if (FAILED(CHL_DsFindLL(pstBpList->pstLinkedListBp, &stBpToFind, fBpCompare, &pstBpFound, &cbOut, FALSE)))
133 | {
134 | logerror(pstLogger, L"%s(): CHL_DsFindLL() failed %u", __FUNCTIONW__, GetLastError());
135 | goto error_return;
136 | }
137 |
138 | // Remove from the linked list
139 | if(FAILED(CHL_DsRemoveLL(pstBpList->pstLinkedListBp, &stBpToFind, TRUE, fBpCompare)))
140 | {
141 | logerror(pstLogger, L"%s(): CHL_DsRemoveLL() failed %u", __FUNCTIONW__, GetLastError());
142 | goto error_return;
143 | }
144 |
145 | // TODO: remove from linked list only after successful removal of actual BP?
146 |
147 | // Replace breakpoint instruction with original opcode
148 | if(pstBpFound->nReferences == 1)
149 | {
150 | dbgwprintf(L"%s(): Removing actual breakpoint at 0x%08x because #references == 1\n", __FUNCTIONW__, pstBpFound->stActualBp.dwAddrInTarget);
151 | if(!fBpRemove_Internal(pstTargetInfo->stProcessInfo.hProcess, pstBpFound->stActualBp.dwAddrInTarget, pstBpFound->stActualBp.bOrigCodeByte))
152 | {
153 | logerror(pstLogger, L"%s(): fBpRemove_Internal() failed %u", __FUNCTIONW__, GetLastError());
154 | goto error_return;
155 | }
156 | }
157 |
158 | CHL_MmFree((void**)&pstBpFound);
159 | return TRUE;
160 |
161 | error_return:
162 | IFPTR_FREE(pstBpFound);
163 | return FALSE;
164 | }
165 |
166 | BOOL fBpFind(PBPLIST pstBpList, __inout PBPINFO pstBpInfo, PINT piBpID)
167 | {
168 | ASSERT(pstBpList);
169 | ASSERT(pstBpInfo);
170 |
171 | DBG_UNREFERENCED_PARAMETER(piBpID);
172 |
173 | BREAKPOINT stBpToFind;
174 | PBREAKPOINT pstBpFound = NULL;
175 |
176 | // TODO: suppoprt usage of piBpID also
177 |
178 | // TODO: assign bpType as well
179 | stBpToFind.stActualBp.dwAddrInTarget = pstBpInfo->dwTargetAddr;
180 |
181 | // Find in linked list
182 | int cbOut = sizeof(pstBpFound);
183 | if(FAILED(CHL_DsFindLL(pstBpList->pstLinkedListBp, &stBpToFind, fBpCompare, (void**)&pstBpFound, &cbOut, TRUE)))
184 | {
185 | logerror(pstLogger, L"%s(): CHL_DsFindLL() failed %u", __FUNCTIONW__, GetLastError());
186 | return FALSE;
187 | }
188 |
189 | // Populate out variable and return TRUE
190 | pstBpInfo->iBpType = pstBpFound->bpType;
191 | pstBpInfo->id = pstBpFound->id;
192 | pstBpInfo->dwTargetAddr = pstBpFound->stActualBp.dwAddrInTarget;
193 |
194 | return TRUE;
195 | }
196 |
197 | static int iGetFirstFreeIdentifier(PINT paiIdentifiers)
198 | {
199 | ASSERT(paiIdentifiers);
200 |
201 | for(int index = 0; index < MAX_BREAKPOINTS; ++index)
202 | {
203 | if(paiIdentifiers[index] == 0)
204 | {
205 | return index + 1;
206 | }
207 | }
208 |
209 | logwarn(pstLogger, L"%s(): No free identifiers!", __FUNCTIONW__);
210 | return -1;
211 | }
212 |
213 | static BOOL fBpInsert_Internal(HANDLE hTargetProcess, DWORD dwTargetAddr, __out PBYTE pbOrigCodeByte)
214 | {
215 | ASSERT(ISVALID_HANDLE(hTargetProcess));
216 | ASSERT(dwTargetAddr > 0);
217 | ASSERT(pbOrigCodeByte);
218 |
219 | BYTE bOrigCode;
220 | SIZE_T bytesReadWritten;
221 |
222 | BYTE bBreakpointInst = OPCODE_BREAKPOINT;
223 |
224 | // Get the original code byte first
225 | if(!ReadProcessMemory(hTargetProcess, (LPCVOID)dwTargetAddr, &bOrigCode, sizeof(bOrigCode), &bytesReadWritten))
226 | {
227 | return FALSE;
228 | }
229 |
230 | // TODO: check bytesReadWritten?
231 |
232 | dbgwprintf(L"Original code byte at 0x%08x: 0x%02x\n", dwTargetAddr, bOrigCode);
233 |
234 | // Overwrite with breakpoint instruction
235 | if(!WriteProcessMemory(hTargetProcess, (LPVOID)dwTargetAddr, &bBreakpointInst, sizeof(BYTE), &bytesReadWritten))
236 | {
237 | return FALSE;
238 | }
239 |
240 | // TODO: check bytesReadWritten?
241 |
242 | *pbOrigCodeByte = bOrigCode;
243 | return TRUE;
244 | }
245 |
246 | static BOOL fBpRemove_Internal(HANDLE hTargetProcess, DWORD dwTargetAddr, BYTE bOrigCodeByte)
247 | {
248 | ASSERT(ISVALID_HANDLE(hTargetProcess));
249 | ASSERT(dwTargetAddr > 0);
250 |
251 | #ifdef _DEBUG
252 |
253 | // Read the original code byte and assert that it is a 0x03 value
254 | BYTE bOrigCode;
255 | SIZE_T bytesReadWritten;
256 |
257 | // Get the original code byte first
258 | if(!ReadProcessMemory(hTargetProcess, (LPCVOID)dwTargetAddr, &bOrigCode, sizeof(bOrigCode), &bytesReadWritten))
259 | {
260 | logwarn(pstLogger, L"%s(): ReadProcessMemory() failed %u", __FUNCTIONW__, GetLastError());
261 | }
262 | else
263 | {
264 | wprintf(L"%s(): Opcode before replacement at 0x%08x: 0x%02x\n", __FUNCTIONW__, dwTargetAddr, bOrigCode);
265 | ASSERT(bOrigCode == OPCODE_BREAKPOINT);
266 | }
267 |
268 | #endif
269 |
270 | if(!WriteProcessMemory(hTargetProcess, (LPVOID)dwTargetAddr, &bOrigCodeByte, sizeof(BYTE), &bytesReadWritten))
271 | {
272 | return FALSE;
273 | }
274 |
275 | // TODO: check bytesReadWritten?
276 |
277 | return TRUE;
278 |
279 | }
280 |
281 | static BOOL fBpCompare(PVOID pvLeft, PVOID pvRight)
282 | {
283 | ASSERT(pvLeft);
284 | ASSERT(pvRight);
285 |
286 | PBREAKPOINT pstBpLeft = (PBREAKPOINT)pvLeft;
287 | PBREAKPOINT pstBpRight = (PBREAKPOINT)pvRight;
288 |
289 | // Only ASM level comparison now
290 | // TODO: SOURCE level comparison and using the identifier
291 |
292 | return pstBpLeft->stActualBp.dwAddrInTarget == pstBpRight->stActualBp.dwAddrInTarget;
293 | }
294 |
--------------------------------------------------------------------------------
/Debugger/Dasm/Dasm.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "DASM.h"
3 |
4 | // global variables
5 | DWORD g_dwInputFileType; // set by fBeginFileScan()
6 | BINFILEINFO g_binFileInfo;
7 |
8 | //// ** Controlling program options **
9 | //// true by default
10 | //BOOL g_fHeaders = TRUE; // NTHeaders, FileHeader, Optional Header
11 | //BOOL g_fDisasm = TRUE;
12 | //
13 | //// false by default
14 | //BOOL g_fExports;
15 | //BOOL g_fImports;
16 |
17 | //int wmain(int argc, WCHAR **argv)
18 | //{
19 | //
20 | //#ifdef UNIT_TESTS_ONLY
21 | // vRunTests();
22 | // //DEngine_FPUUnitTest();
23 | // //DEngine_MMXUnitTest();
24 | // //DEngine_SSEUnitTest();
25 | // return 0;
26 | //#else
27 | //
28 | // WCHAR wszFilepath[MAX_PATH+1] = L"";
29 | // WCHAR wszOutFile[MAX_PATH+1] = L"";
30 | //
31 | // HANDLE hFile = NULL, hFileObj = NULL, hFileView = NULL;
32 | // IMAGE_NT_HEADERS *pNTHeaders = NULL;
33 | // DWORD dwCodeSecOffset = 0;
34 | // DWORD dwSizeOfCodeSection = 0;
35 | //
36 | // NCODE_LOCS NNonCodeLocs;
37 | //
38 | // //wprintf_s(L"%d %d %d\n", sizeof(long long), sizeof(INT), sizeof(DWORD));
39 | // //wprintf_s(L"sizeof(IMAGE_IMPORT_DESCRIPTOR) = %d\n", sizeof(IMAGE_IMPORT_DESCRIPTOR));
40 | //
41 | // #ifdef NDEBUG
42 | // // Opening statement
43 | // wprintf(L"Shishir's Garage project::DASM v%s, a disassembler for 32bit PE files\
44 | // \nCoder: Shishir Bhat {shishirb.asm@gmail.com}\
45 | // \nCopyright: None but don't forget to include my name as a reference in your code/webpage. :)\n\n", DASM_VERSION_STR);
46 | // #endif
47 | //
48 | // /*
49 | // * If no arguments are specified, then prompt user for path to
50 | // * file to disassemble.
51 | // * If one argument is given, then assume that as the file to be
52 | // * disassembled.
53 | // * If there are 2 arguments, then assume the first one as the
54 | // * exe/dll/... file, and the second one as the output file in
55 | // * which we must write the output.
56 | // *
57 | // * todo: No support for output file yet!!
58 | // */
59 | // //if(argc == 1)
60 | // //{
61 | // // wprintf_s(L"Enter the path to file: ");
62 | // // wscanf_s(L"%s", wszFilepath);
63 | // //}
64 | // //else if(argc == 2)
65 | // //{
66 | // // // input file in argv[1]
67 | // // wcscpy_s(wszFilepath, MAX_PATH+1, argv[1]);
68 | // //}
69 | // //else
70 | // //{
71 | // // wprintf_s(L"usage: %s []\n", argv[0]);
72 | // // return 1;
73 | // //}
74 | //
75 | // //if(!fCmdArgsHandler(argc, argv, wszFilepath, _countof(wszFilepath)))
76 | // //{
77 | // // wprintf_s(L"main(): Unable to parse command line arguments\n");
78 | // // wprintf_s(L"usage: %s\n\t[inputFile]\n\t[-exports|-e]\n\t[-imports|-i]\n\t[-headers|-h]\n\t[-disasm|-d]\n", argv[0]);
79 | // // return 1;
80 | // //}
81 | //
82 | // //wprintf_s(L"Using input file: %s\nOutput file: %s\n", wszFilepath, wszOutFile);
83 | // //wprintf_s(L"Using input file: %s\n", wszFilepath);
84 | //
85 | // //if( ! fOpenAndMapFile(wszFilepath, &hFile, &hFileObj, &hFileView) )
86 | // //{
87 | // // wprintf_s(L"Error opening input file\n");
88 | // // return 1;
89 | // //}
90 | //
91 | // wprintf_s(L"********************************\nDisassembling file: %s\n",
92 | // wszFilepath);
93 | //
94 | // __try
95 | // {
96 | // // dump information from headers
97 | // if( ! fBeginFileScan(hFile, hFileObj, hFileView) )
98 | // {
99 | // wprintf_s(L"main(): fBeginFileScan() error\n");
100 | // return 1;
101 | // }
102 | //
103 | // //if(g_fDisasm)
104 | // //{
105 | // // // get pointer to code section
106 | // // if( ! fGetPtrToCode((DWORD)hFileView, g_binFileInfo.pNTHeaders,
107 | // // &dwCodeSecOffset, &dwSizeOfCodeSection, &g_binFileInfo.dwVirtBaseOfCode) )
108 | // // {
109 | // // wprintf_s(L"Cannot retrieve pointer to code section. Aborting...\n");
110 | // // return 1;
111 | // // }
112 | //
113 | // // //memset(&NNonCodeLocs, 0, sizeof(NNonCodeLocs));
114 | //
115 | // // // Check if the IAT is present within the .text section
116 | // // // Doing this will lead to a clearer disassembly
117 | // //
118 | // // //NNonCodeLocs.hFileBase = hFileView;
119 | //
120 | // // // Notes: Under construction
121 | // // // begin disassembly
122 | // // // fDisassembler(&NNonCodeLocs, g_binFileInfo.dwVirtBaseOfCode);
123 | //
124 | // // fDoDisassembly( (DWORD*)dwCodeSecOffset, dwSizeOfCodeSection,
125 | // // g_binFileInfo.dwVirtBaseOfCode );
126 | // //}// if(g_fDisasm)
127 | //
128 | // return 0;
129 | // }
130 | // __finally
131 | // {
132 | // if(hFile != NULL && hFileObj != NULL && hFileView != NULL)
133 | // fCloseFile(hFile, hFileObj, hFileView);
134 | // }
135 | //
136 | //#endif // UNIT_TESTS_ONLY
137 | //
138 | //}// wmain()
139 |
140 |
141 | // Unit testing of individual functions
142 | void vRunTests()
143 | {
144 |
145 | // Util_vSplitModRMByte()
146 | BYTE bModRM;
147 | BYTE bMod;
148 | BYTE bReg;
149 | BYTE bRM;
150 |
151 | bModRM = 0x7c; // 01 111 100
152 | bMod = bReg = bRM = 0xff;
153 | Util_vSplitModRMByte(bModRM, &bMod, &bReg, &bRM);
154 | if( bMod != 1 || bReg != 7 || bRM != 4)
155 | wprintf_s(L"!FAILED: Util_vSplitModRMByte(): %x, %x, %x, %x\n",
156 | bModRM, bMod, bReg, bRM);
157 | else
158 | wprintf_s(L"*Passed: Util_vSplitModRMByte(): %x, %x, %x, %x\n",
159 | bModRM, bMod, bReg, bRM);
160 |
161 | bModRM = 0xff; // 11 111 111
162 | bMod = bReg = bRM = 0;
163 | Util_vSplitModRMByte(bModRM, &bMod, &bReg, &bRM);
164 | if( bMod != 3 || bReg != 7 || bRM != 7)
165 | wprintf_s(L"!FAILED: Util_vSplitModRMByte(): %x, %x, %x, %x\n",
166 | bModRM, bMod, bReg, bRM);
167 | else
168 | wprintf_s(L"*Passed: Util_vSplitModRMByte(): %x, %x, %x, %x\n",
169 | bModRM, bMod, bReg, bRM);
170 |
171 | // test Util_vGetDWBits()
172 | BYTE bD;
173 | BYTE bW;
174 |
175 | Util_vGetDWBits(0x00, &bD, &bW);
176 | if(bD != 0 || bW != 0)
177 | wprintf_s(L"!FAILED: Util_vGetDWBits(): %x, %x, %x\n", 0x00, bD, bW);
178 | else
179 | wprintf_s(L"*Passed: Util_vGetDWBits(): %x, %x, %x\n", 0x00, bD, bW);
180 |
181 | Util_vGetDWBits(0x03, &bD, &bW);
182 | if(bD != 1 || bW != 1)
183 | wprintf_s(L"!FAILED: Util_vGetDWBits(): %x, %x, %x\n", 0x03, bD, bW);
184 | else
185 | wprintf_s(L"*Passed: Util_vGetDWBits(): %x, %x, %x\n", 0x03, bD, bW);
186 |
187 | Util_vGetDWBits(0x01, &bD, &bW);
188 | if(bD != 0 || bW != 1)
189 | wprintf_s(L"!FAILED: Util_vGetDWBits(): %x, %x, %x\n", 0x01, bD, bW);
190 | else
191 | wprintf_s(L"*Passed: Util_vGetDWBits(): %x, %x, %x\n", 0x01, bD, bW);
192 |
193 | Util_vGetDWBits(0x02, &bD, &bW);
194 | if(bD != 1 || bW != 0)
195 | wprintf_s(L"!FAILED: Util_vGetDWBits(): %x, %x, %x\n", 0x02, bD, bW);
196 | else
197 | wprintf_s(L"*Passed: Util_vGetDWBits(): %x, %x, %x\n", 0x02, bD, bW);
198 |
199 | /*
200 | * Util_vTwosComplementByte()
201 | */
202 | BYTE ch = 0xe8;
203 | BYTE chCompl; // 2's complement(ch)
204 | Util_vTwosComplementByte(ch, &chCompl);
205 | if(chCompl != 0x18)
206 | wprintf_s(L"!FAILED: Util_vTwosComplementByte(): %x, %x\n", ch, chCompl);
207 | else
208 | wprintf_s(L"*Passed: Util_vTwosComplementByte(): %x, %x\n", ch, chCompl);
209 |
210 | ch = 0x00;
211 | Util_vTwosComplementByte(ch, &chCompl);
212 | if(chCompl != 0x00)
213 | wprintf_s(L"!FAILED: Util_vTwosComplementByte(): %x, %x\n", ch, chCompl);
214 | else
215 | wprintf_s(L"*Passed: Util_vTwosComplementByte(): %x, %x\n", ch, chCompl);
216 |
217 | ch = 0x7f;
218 | Util_vTwosComplementByte(ch, &chCompl);
219 | if(chCompl != (BYTE)0x81)
220 | wprintf_s(L"!FAILED: Util_vTwosComplementByte(): %x, %x\n", ch, chCompl);
221 | else
222 | wprintf_s(L"*Passed: Util_vTwosComplementByte(): %x, %x\n", ch, chCompl);
223 |
224 | ch = 0xff;
225 | Util_vTwosComplementByte(ch, &chCompl);
226 | if(chCompl != 0x01)
227 | wprintf_s(L"!FAILED: Util_vTwosComplementByte(): %x, %x\n", ch, chCompl);
228 | else
229 | wprintf_s(L"*Passed: Util_vTwosComplementByte(): %x, %x\n", ch, chCompl);
230 |
231 | /*
232 | * Util_vTwosComplementInt()
233 | */
234 | INT i = 0x002b34e8;
235 | INT iCompl; // 2's complement(ch)
236 | INT iTemp;
237 |
238 | iTemp = ((i ^ 0xffffffff) + 1);
239 | Util_vTwosComplementInt(i, &iCompl);
240 | if(iCompl != iTemp)
241 | wprintf_s(L"!FAILED: Util_vTwosComplementInt(): %x, %x\n", i, iCompl);
242 | else
243 | wprintf_s(L"*Passed: Util_vTwosComplementInt(): %x, %x\n", i, iCompl);
244 |
245 | i = 0x00;
246 | iTemp = ((i ^ 0xffffffff) + 1);
247 | Util_vTwosComplementInt(i, &iCompl);
248 | if(iCompl != iTemp)
249 | wprintf_s(L"!FAILED: Util_vTwosComplementInt(): %x, %x\n", i, iCompl);
250 | else
251 | wprintf_s(L"*Passed: Util_vTwosComplementInt(): %x, %x\n", i, iCompl);
252 |
253 | i = 0x7fffffff;
254 | iTemp = ((i ^ 0xffffffff) + 1);
255 | Util_vTwosComplementInt(i, &iCompl);
256 | if(iCompl != iTemp)
257 | wprintf_s(L"!FAILED: Util_vTwosComplementInt(): %x, %x\n", i, iCompl);
258 | else
259 | wprintf_s(L"*Passed: Util_vTwosComplementInt(): %x, %x\n", i, iCompl);
260 |
261 | i = 0xffffffff;
262 | iTemp = ((i ^ 0xffffffff) + 1);
263 | Util_vTwosComplementInt(i, &iCompl);
264 | if(iCompl != iTemp)
265 | wprintf_s(L"!FAILED: Util_vTwosComplementInt(): %x, %x\n", i, iCompl);
266 | else
267 | wprintf_s(L"*Passed: Util_vTwosComplementInt(): %x, %x\n", i, iCompl);
268 |
269 | i = 0x8b00401b;
270 | iTemp = ((i ^ 0xffffffff) + 1);
271 | Util_vTwosComplementInt(i, &iCompl);
272 | if(iCompl != iTemp)
273 | wprintf_s(L"!FAILED: Util_vTwosComplementInt(): %x, %x\n", i, iCompl);
274 | else
275 | wprintf_s(L"*Passed: Util_vTwosComplementInt(): %x, %x\n", i, iCompl);
276 |
277 | i = 0x80000000;
278 | iTemp = ((i ^ 0xffffffff) + 1);
279 | Util_vTwosComplementInt(i, &iCompl);
280 | if(iCompl != iTemp)
281 | wprintf_s(L"!FAILED: Util_vTwosComplementInt(): %x, %x\n", i, iCompl);
282 | else
283 | wprintf_s(L"*Passed: Util_vTwosComplementInt(): %x, %x\n", i, iCompl);
284 |
285 | }// vRunTests()
286 |
--------------------------------------------------------------------------------
/Debugger/Lib/include/BinarySearchTree.h:
--------------------------------------------------------------------------------
1 |
2 | // BinarySearchTree.h
3 | // The quintessential data structure in computer science - the binary search tree
4 | // Shishir Bhat (http://www.shishirbhat.com)
5 | // History
6 | // 2016/01/28 Initial version. Create, destroy, insert and traverse.
7 | //
8 |
9 | #ifndef _CHL_BINARY_SEARCHTREE_H
10 | #define _CHL_BINARY_SEARCHTREE_H
11 |
12 | #ifdef __cplusplus
13 | extern "C" {
14 | #endif
15 |
16 | #include "Defines.h"
17 | #include "MemFunctions.h"
18 |
19 | typedef enum _bstIerationType {
20 | BstIterationType_PreOrder,
21 | BstIterationType_InOrder,
22 | BstIterationType_PostOrder
23 | } CHL_BstIterationType;
24 |
25 | typedef struct _bstNode {
26 | CHL_KEY chlKey;
27 | CHL_VAL chlVal;
28 | UINT treeSize; // #nodes in the subtree rooted at this node
29 |
30 | struct _bstNode* pLeft;
31 | struct _bstNode* pRight;
32 | //struct _bstNode* pParent;
33 |
34 | } BSTNODE, *PBSTNODE;
35 |
36 | // Foward declare the iterator struct
37 | typedef struct _bstIterator CHL_BST_ITERATOR, *PCHL_BST_ITERATOR;
38 |
39 | // Struct representing the BST object
40 | typedef struct _bstTree CHL_BSTREE, *PCHL_BSTREE;
41 | struct _bstTree {
42 | CHL_KEYTYPE keyType;
43 | CHL_VALTYPE valType;
44 | BOOL fValIsInHeap;
45 | PBSTNODE pRoot;
46 |
47 | CHL_CompareFn fnKeyCompare;
48 |
49 | // Pointers to binary search tree methods
50 |
51 | HRESULT (*Create)
52 | (
53 | _Out_ PCHL_BSTREE pbst,
54 | _In_ CHL_KEYTYPE keyType,
55 | _In_ CHL_VALTYPE valType,
56 | _In_ CHL_CompareFn pfnKeyCompare,
57 | _In_opt_ BOOL fValInHeapMem
58 | );
59 |
60 | HRESULT (*Destroy)(_In_ PCHL_BSTREE pbst);
61 |
62 | HRESULT (*Insert)
63 | (
64 | _In_ PCHL_BSTREE pbst,
65 | _In_ PCVOID pvkey,
66 | _In_ int iKeySize,
67 | _In_ PCVOID pvVal,
68 | _In_ int iValSize
69 | );
70 |
71 | HRESULT (*Find)
72 | (
73 | _In_ PCHL_BSTREE pbst,
74 | _In_ PCVOID pvkey,
75 | _In_ int iKeySize,
76 | _Inout_opt_ PVOID pvVal,
77 | _Inout_opt_ PINT pValsize,
78 | _In_opt_ BOOL fGetPointerOnly
79 | );
80 |
81 | HRESULT (*FindMax)
82 | (
83 | _In_ PCHL_BSTREE pbst,
84 | _Inout_opt_ PVOID pvKeyOut,
85 | _Inout_opt_ PINT pKeySizeOut,
86 | _In_opt_ BOOL fGetPointerOnly
87 | );
88 |
89 | HRESULT (*FindMin)
90 | (
91 | _In_ PCHL_BSTREE pbst,
92 | _Inout_opt_ PVOID pvKeyOut,
93 | _Inout_opt_ PINT pKeySizeOut,
94 | _In_opt_ BOOL fGetPointerOnly
95 | );
96 |
97 | HRESULT (*FindFloor)
98 | (
99 | _In_ PCHL_BSTREE pbst,
100 | _In_ PCVOID pvKey,
101 | _In_ int iKeySize,
102 | _Inout_opt_ PVOID pvKeyOut,
103 | _Inout_opt_ PINT pKeySizeOut,
104 | _In_opt_ BOOL fGetPointerOnly
105 | );
106 |
107 | HRESULT (*FindCeil)
108 | (
109 | _In_ PCHL_BSTREE pbst,
110 | _In_ PCVOID pvKey,
111 | _In_ int iKeySize,
112 | _Inout_opt_ PVOID pvKeyOut,
113 | _Inout_opt_ PINT pKeySizeOut,
114 | _In_opt_ BOOL fGetPointerOnly
115 | );
116 |
117 | HRESULT (*InitIterator)
118 | (
119 | _Out_ PCHL_BST_ITERATOR pItr,
120 | _In_ PCHL_BSTREE pbst,
121 | _In_ CHL_BstIterationType itrType
122 | );
123 |
124 | HRESULT (*GetNext)
125 | (
126 | _In_ PCHL_BST_ITERATOR pItr,
127 | _Inout_opt_ PCVOID pvKey,
128 | _Inout_opt_ PINT pKeysize,
129 | _Inout_opt_ PVOID pvVal,
130 | _Inout_opt_ PINT pValSize,
131 | _In_opt_ BOOL fGetPointerOnly
132 | );
133 |
134 | };
135 |
136 | // Iterator used to traverse the tree
137 | struct _bstIterator {
138 | CHL_BstIterationType itType;
139 | PCHL_BSTREE pbst;
140 | PBSTNODE pCur;
141 |
142 | // Access methods
143 |
144 | HRESULT(*GetNext)
145 | (
146 | _In_ PCHL_BST_ITERATOR pItr,
147 | _Inout_opt_ PCVOID pvKey,
148 | _Inout_opt_ PINT pKeysize,
149 | _Inout_opt_ PVOID pvVal,
150 | _Inout_opt_ PINT pValSize,
151 | _In_opt_ BOOL fGetPointerOnly
152 | );
153 | };
154 |
155 |
156 | // -------------------------------------------
157 | // Functions exported
158 |
159 | // Creates a binary search tree and returns a pointer to CHL_BSTREE object
160 | // which can be used for later operations on the tree.
161 | // Params:
162 | // pbst : Pointer to a CHL_BSTREE object to initialize
163 | // keyType : Type of variable that is used as key - refer to definition of CHL_KEYTYPE
164 | // valType : Type of value that is stored - refer to definition of CHL_VALTYPE
165 | // pfnKeyCompare : Pointer to function of type CHL_CompareFn that can compare two keys
166 | // fValInHeapMem : Set this to true if the value (type is CHL_VT_POINTER) is allocated memory on the heap.
167 | // This indicates the tree to free it when an entry is removed.
168 | //
169 | DllExpImp HRESULT CHL_DsCreateBST
170 | (
171 | _Out_ PCHL_BSTREE pbst,
172 | _In_ CHL_KEYTYPE keyType,
173 | _In_ CHL_VALTYPE valType,
174 | _In_ CHL_CompareFn pfnKeyCompare,
175 | _In_opt_ BOOL fValInHeapMem
176 | );
177 |
178 | // Destroy the tree by removing all key-value pairs from the tree.
179 | // The CHL_BSTREE object itself is also destroyed.
180 | // Params:
181 | // pbst: Pointer to the BST object returned by CHL_DsCreateBST function.
182 | //
183 | DllExpImp HRESULT CHL_DsDestroyBST(_In_ PCHL_BSTREE pbst);
184 |
185 | // Inserts a key,value pair into the tree. If the key already exists, then the value is over-written
186 | // with the new value. If both the key and value already exist, then nothing is changed in the tree.
187 | // Params:
188 | // pbst : Pointer to the binary search tree object returned by CHL_DsCreateBST function.
189 | // pvkey : Pointer to the key. For primitive types, this is the primitive value casted to a PCVOID.
190 | // iKeySize: Size of the key in bytes. For null-terminated strings, zero may be passed.
191 | // pvVal : Value to be stored. Please see documentation for details.
192 | // iValSize: Size of the value in bytes. For null-terminated strings, zero may be passed.
193 | //
194 | DllExpImp HRESULT CHL_DsInsertBST
195 | (
196 | _In_ PCHL_BSTREE pbst,
197 | _In_ PCVOID pvkey,
198 | _In_ int iKeySize,
199 | _In_ PCVOID pvVal,
200 | _In_ int iValSize
201 | );
202 |
203 | // Find the specified key in the binary search tree.
204 | // Params:
205 | // pbst : Pointer to the binary search tree object returned by CHL_DsCreateBST function.
206 | // pvkey : Pointer to the key. For primitive types, this is the primitive value casted to a PCVOID.
207 | // iKeySize : Size of the key in bytes. For null-terminated strings, zero may be passed.
208 | // pvVal : Optional. Pointer to a buffer to receive the value, if found.
209 | // pValsize : Optional. Size of the value buffer in bytes. If specified size is insufficient, the function
210 | // returns the required size back in this parameter.
211 | // fGetPointerOnly : Applies to value of type CHL_VT_USEROBJECT/CHL_VT_STRING/CHL_VT_WSTRING -
212 | // If this is TRUE, function returns a pointer to the stored value in the buffer pvVal.
213 | // Otherwise, the full value is copied into the pvVal buffer.
214 | //
215 | DllExpImp HRESULT CHL_DsFindBST
216 | (
217 | _In_ PCHL_BSTREE pbst,
218 | _In_ PCVOID pvkey,
219 | _In_ int iKeySize,
220 | _Inout_opt_ PVOID pvVal,
221 | _Inout_opt_ PINT pValsize,
222 | _In_opt_ BOOL fGetPointerOnly
223 | );
224 |
225 | // Get the maximum key in the binary search tree
226 | // Params:
227 | // pbst : Pointer to the binary search tree object returned by CHL_DsCreateBST function.
228 | // pvKey : Optional. Pointer to buffer to receive the maximum key.
229 | // pKeySize : Optional. Size of the key buffer in bytes. If specified size is insufficient, the function
230 | // returns the required size back in this parameter.
231 | // fGetPointerOnly : Applies to value of type CHL_VT_USEROBJECT/CHL_VT_STRING/CHL_VT_WSTRING -
232 | // If this is TRUE, function returns a pointer to the stored key in the buffer pvKeyOut.
233 | // Otherwise, the full value is copied into the pKeySizeOut buffer.
234 | //
235 | DllExpImp HRESULT CHL_DsFindMaxBST
236 | (
237 | _In_ PCHL_BSTREE pbst,
238 | _Inout_opt_ PVOID pvKeyOut,
239 | _Inout_opt_ PINT pKeySizeOut,
240 | _In_opt_ BOOL fGetPointerOnly
241 | );
242 |
243 | // Get the minimum key in the binary search tree
244 | // Params:
245 | // pbst : Pointer to the binary search tree object returned by CHL_DsCreateBST function.
246 | // pvKey : Optional. Pointer to buffer to receive the minimum key.
247 | // pKeySize : Optional. Size of the key buffer in bytes. If specified size is insufficient, the function
248 | // returns the required size back in this parameter.
249 | // fGetPointerOnly : Applies to value of type CHL_VT_USEROBJECT/CHL_VT_STRING/CHL_VT_WSTRING -
250 | // If this is TRUE, function returns a pointer to the stored key in the buffer pvKeyOut.
251 | // Otherwise, the full value is copied into the pKeySizeOut buffer.
252 | //
253 | DllExpImp HRESULT CHL_DsFindMinBST
254 | (
255 | _In_ PCHL_BSTREE pbst,
256 | _Inout_opt_ PVOID pvKey,
257 | _Inout_opt_ PINT pKeysize,
258 | _In_opt_ BOOL fGetPointerOnly
259 | );
260 |
261 | // Get the floor of specified key in the binary search tree
262 | // Params:
263 | // pbst : Pointer to the binary search tree object returned by CHL_DsCreateBST function.
264 | // pvKey : Pointer to the key. For primitive types, this is the primitive value casted to a PCVOID.
265 | // iKeySize : Size of the key in bytes. For null-terminated strings, zero may be passed.
266 | // returns the required size back in this parameter.
267 | // pvKeyOut : Optional. Pointer to buffer to receive the floor key, if found.
268 | // pKeySizeOut : Optional. Size of the key buffer in bytes. If specified size is insufficient, the function
269 | // returns the required size back in this parameter.
270 | // fGetPointerOnly : Applies to value of type CHL_VT_USEROBJECT/CHL_VT_STRING/CHL_VT_WSTRING -
271 | // If this is TRUE, function returns a pointer to the stored key in the buffer pvKeyOut.
272 | // Otherwise, the full value is copied into the pKeySizeOut buffer.
273 | //
274 | DllExpImp HRESULT CHL_DsFindFloorBST
275 | (
276 | _In_ PCHL_BSTREE pbst,
277 | _In_ PCVOID pvKey,
278 | _In_ int iKeySize,
279 | _Inout_opt_ PVOID pvKeyOut,
280 | _Inout_opt_ PINT pKeySizeOut,
281 | _In_opt_ BOOL fGetPointerOnly
282 | );
283 |
284 | // Get the ceil of specified key in the binary search tree
285 | // Params:
286 | // pbst : Pointer to the binary search tree object returned by CHL_DsCreateBST function.
287 | // pvKey : Pointer to the key. For primitive types, this is the primitive value casted to a PCVOID.
288 | // iKeySize : Size of the key in bytes. For null-terminated strings, zero may be passed.
289 | // returns the required size back in this parameter.
290 | // pvKeyOut : Optional. Pointer to buffer to receive the ceil key, if found.
291 | // pKeySizeOut : Optional. Size of the key buffer in bytes. If specified size is insufficient, the function
292 | // returns the required size back in this parameter.
293 | // fGetPointerOnly : Applies to value of type CHL_VT_USEROBJECT/CHL_VT_STRING/CHL_VT_WSTRING -
294 | // If this is TRUE, function returns a pointer to the stored key in the buffer pvKeyOut.
295 | // Otherwise, the full value is copied into the pKeySizeOut buffer.
296 | //
297 | DllExpImp HRESULT CHL_DsFindCeilBST
298 | (
299 | _In_ PCHL_BSTREE pbst,
300 | _In_ PCVOID pvKey,
301 | _In_ int iKeySize,
302 | _Inout_opt_ PVOID pvKeyOut,
303 | _Inout_opt_ PINT pKeySizeOut,
304 | _In_opt_ BOOL fGetPointerOnly
305 | );
306 |
307 | // Initialize the iterator object for use with the specified BST.
308 | // Params:
309 | // pItr : Pointer to the iterator object to initialize.
310 | // pbst : Pointer to the binary search tree object returned by CHL_DsCreateBST function.
311 | // itrType : Type of iteration to perform (PreOrder/InOrder/PostOrder).
312 | //
313 | DllExpImp HRESULT CHL_DsInitIteratorBST
314 | (
315 | _Out_ PCHL_BST_ITERATOR pItr,
316 | _In_ PCHL_BSTREE pbst,
317 | _In_ CHL_BstIterationType itrType
318 | );
319 |
320 | // Get the next entry in the tree using the specified iterator object.
321 | // Params:
322 | // pItr : The iterator object that was initialized by CHL_DsInitIteratorBST.
323 | // pvKey : Optional. Pointer to buffer to receive the key of the next entry.
324 | // pKeySize : Optional. Size of the key buffer in bytes. If specified size is insufficient, the function
325 | // returns the required size back in this parameter.
326 | // pvVal : TODO.
327 | // pvalsize : TODO.
328 | // fGetPointerOnly : TODO.
329 | //
330 | DllExpImp HRESULT CHL_DsGetNextBST
331 | (
332 | _In_ PCHL_BST_ITERATOR pItr,
333 | _Inout_opt_ PVOID pvKey,
334 | _Inout_opt_ PINT pKeysize,
335 | _Inout_opt_ PVOID pvVal,
336 | _Inout_opt_ PINT pValSize,
337 | _In_opt_ BOOL fGetPointerOnly
338 | );
339 |
340 | #ifdef __cplusplus
341 | }
342 | #endif
343 |
344 | #endif // _CHL_BINARY_SEARCHTREE_H
345 |
--------------------------------------------------------------------------------
/Debugger/UICreator.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Inc\UICreator.h"
3 | #include "Inc\DebuggerDP.h"
4 | #include "Inc\SourceHelpers.h"
5 | #include "Defines.h"
6 |
7 | extern HINSTANCE g_hMainInstance;
8 | extern PLOGGER pstLogger;
9 |
10 | static int aiColumnSizePercent_Threads[] = { 12, 12, 52, 12, 12 };
11 | static int aiColumnSizePercent_Regs[] = { 15, 85 };
12 |
13 | static WCHAR *aszColumnNames_Threads[] = { L"ThreadId", L"EIPLocation", L"Function", L"Type", L"Priority" };
14 | static WCHAR *aszColumnNames_Regs[] = { L"Name", L"Value" };
15 |
16 | struct _FontSelection {
17 | LOGFONT stLogFont;
18 | TEXTMETRIC stTextMetric;
19 | };
20 |
21 | // File local functions
22 | static BOOL fInsertTabItem(HWND hTab, WCHAR *pszText, __out int *piNewIndex, __out DWORD *pdwErrCode);
23 | BOOL fGetFixedWidthFont(HWND hWindow, HFONT *phFont);
24 | static int CALLBACK EnumFontCallback(
25 | const LOGFONT *lpelfe,
26 | const TEXTMETRIC *lpntme,
27 | DWORD FontType,
28 | LPARAM lParam);
29 |
30 | BOOL fCreateMainTabControl(HWND hMainWnd, __out HWND *phTabControl, DWORD *pdwErrCode)
31 | {
32 | ASSERT(ISVALID_HANDLE(hMainWnd));
33 | ASSERT(phTabControl);
34 | ASSERT(pdwErrCode);
35 |
36 | RECT rcClientArea;
37 | HWND hTab = NULL;
38 |
39 | if(!GetClientRect(hMainWnd, &rcClientArea))
40 | {
41 | // todo: log error
42 | goto error_return;
43 | }
44 |
45 | hTab = CreateWindow(WC_TABCONTROL, NULL, WS_CHILD|WS_VISIBLE|WS_BORDER, rcClientArea.left + 5, rcClientArea.top + 5,
46 | rcClientArea.right - 10, rcClientArea.bottom - 10, hMainWnd, (HMENU)IDC_MAINTAB, g_hMainInstance, NULL);
47 |
48 | if(ISNULL(hTab))
49 | {
50 | // todo: log error
51 | goto error_return;
52 | }
53 |
54 | *phTabControl = hTab;
55 | return TRUE;
56 |
57 | error_return:
58 | *pdwErrCode = GetLastError();
59 | return FALSE;
60 | }
61 |
62 | BOOL fCreateTabPage(HWND hTab, __out PTABPAGEINFO pstTabPageInfo, __out DWORD *pdwErrCode)
63 | {
64 | ASSERT(ISVALID_HANDLE(hTab));
65 | ASSERT(pstTabPageInfo);
66 | ASSERT(pdwErrCode);
67 |
68 | RECT rcTabWindow;
69 | RECT rcTabDisplay;
70 |
71 | int iNewIndex = -1;
72 | HWND hEditDisass, hListCStack, hListRegisters, hListThreads, hTabBottom, hEditCommand, hStaticCommand;
73 |
74 | HFONT hFixedFont = NULL;
75 |
76 | // Init all handles to NULL
77 | hEditDisass = hListCStack = hListRegisters = hListThreads = hTabBottom = hEditCommand = hStaticCommand = NULL;
78 |
79 | // Insert a new tab item
80 | if(!fInsertTabItem(hTab, L"Test", &iNewIndex, NULL))
81 | {
82 | // todo: log
83 | goto error_return;
84 | }
85 | ASSERT(iNewIndex > -1);
86 |
87 | if(!GetWindowRect(hTab, &rcTabWindow))
88 | {
89 | // todo: log
90 | goto error_return;
91 | }
92 |
93 | CopyRect(&rcTabDisplay, &rcTabWindow);
94 | SendMessage(hTab, TCM_ADJUSTRECT, FALSE, (LPARAM)&rcTabDisplay);
95 |
96 | ScreenToClient(hTab, (LPPOINT)&rcTabDisplay.left);
97 | ScreenToClient(hTab, (LPPOINT)&rcTabDisplay.right);
98 |
99 | // Calculate width for the text static 'Command:' (without quotes) and the edit control
100 | WCHAR szTextCommand[] = L"Command:";
101 | int iTextWidth, iTextHeight;
102 |
103 | if(FAILED(CHL_GuiGetTextArea(hTab, wcslen(szTextCommand), &iTextWidth, &iTextHeight)))
104 | {
105 | logerror(pstLogger, L"%s(): CHL_GuiGetTextArea() failed %u", GetLastError());
106 | goto error_return;
107 | }
108 |
109 | int iCursorHeight = GetSystemMetrics(SM_CYCURSOR);
110 |
111 | // Bounding rectangle of the tab page's display area
112 | int x0 = rcTabDisplay.left;
113 | int y0 = rcTabDisplay.top;
114 | int xMax = rcTabDisplay.right;
115 | int yMax = rcTabDisplay.bottom;
116 |
117 | int tabWidth = xMax - x0;
118 | int tabHeight = yMax - y0;
119 |
120 | int liHeight = (tabHeight - iCursorHeight) * 0.33;
121 |
122 | int w50 = tabWidth / 2; // width 1/2
123 | int h75 = tabHeight * 0.75; // height 3/4
124 | int h25 = tabHeight - h75; // height 1/4
125 |
126 | // Get a fixed width font for use in the child controls
127 | if(!fGetFixedWidthFont(hTab, &hFixedFont))
128 | {
129 | goto error_return;
130 | }
131 |
132 | // Create the disass window
133 | hEditDisass = CreateWindow(
134 | WC_EDIT,
135 | NULL,
136 | WS_CHILD | WS_BORDER | WS_VISIBLE | ES_LEFT | ES_MULTILINE | ES_READONLY,
137 | x0,
138 | y0,
139 | w50,
140 | h75,
141 | hTab,
142 | (HMENU)IDC_EDIT_DISASS,
143 | g_hMainInstance,
144 | NULL);
145 |
146 | ISNULL_GOTO(hEditDisass, error_return);
147 | SendMessage(hEditDisass, WM_SETFONT, (WPARAM)hFixedFont, FALSE);
148 |
149 | RECT rcTemp;
150 |
151 | // Three list views
152 | hListCStack = CreateWindow(
153 | WC_LISTVIEW,
154 | NULL,
155 | WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT,
156 | x0 + w50,
157 | y0,
158 | w50,
159 | liHeight,
160 | hTab,
161 | (HMENU)IDC_LIST_CALLSTACK,
162 | g_hMainInstance,
163 | NULL);
164 |
165 | ISNULL_GOTO(hListCStack, error_return);
166 | GetWindowRect(hListCStack, &rcTemp);
167 |
168 | // TODO: initialize columns
169 |
170 | hListRegisters = CreateWindow(
171 | WC_LISTVIEW,
172 | NULL,
173 | WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT,
174 | x0 + w50,
175 | y0 + liHeight,
176 | w50,
177 | liHeight,
178 | hTab,
179 | (HMENU)IDC_LIST_REGISTERS,
180 | g_hMainInstance,
181 | NULL);
182 |
183 | ISNULL_GOTO(hListRegisters, error_return);
184 |
185 | SendMessage(hListRegisters, WM_SETFONT, (WPARAM)hFixedFont, FALSE);
186 | GetWindowRect(hListRegisters, &rcTemp);
187 |
188 | // Initialize columns
189 | if(FAILED(CHL_GuiInitListViewColumns(hListRegisters, aszColumnNames_Regs, NELEMS_ARRAY(aszColumnNames_Regs), aiColumnSizePercent_Regs)))
190 | {
191 | // todo: log error
192 | goto error_return;
193 | }
194 |
195 | hListThreads = CreateWindow(
196 | WC_LISTVIEW,
197 | NULL,
198 | WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT,
199 | x0 + w50,
200 | y0 + liHeight + liHeight,
201 | w50,
202 | liHeight,
203 | hTab,
204 | (HMENU)IDC_LIST_THREADS,
205 | g_hMainInstance,
206 | NULL);
207 |
208 | ISNULL_GOTO(hListThreads, error_return);
209 | SendMessage(hListThreads, WM_SETFONT, (WPARAM)hFixedFont, FALSE);
210 |
211 | GetWindowRect(hListThreads, &rcTemp);
212 |
213 | // Initialize columns
214 | if(FAILED(CHL_GuiInitListViewColumns(hListThreads, aszColumnNames_Threads, NELEMS_ARRAY(aszColumnNames_Threads), aiColumnSizePercent_Threads)))
215 | {
216 | // todo: log error
217 | goto error_return;
218 | }
219 |
220 | // Command static and edit controls
221 | hStaticCommand = CreateWindow(
222 | WC_STATIC,
223 | NULL,
224 | WS_CHILD | WS_BORDER | WS_VISIBLE,
225 | x0 + w50,
226 | yMax - iCursorHeight,
227 | iTextWidth,
228 | iCursorHeight,
229 | hTab,
230 | NULL,
231 | g_hMainInstance,
232 | NULL);
233 |
234 | ISNULL_GOTO(hStaticCommand, error_return);
235 | SendMessage(hStaticCommand, WM_SETTEXT, 0, (LPARAM)szTextCommand);
236 |
237 | GetWindowRect(hStaticCommand, &rcTemp);
238 | hEditCommand = CreateWindow(
239 | WC_EDIT,
240 | NULL,
241 | WS_CHILD | WS_BORDER | WS_VISIBLE | ES_LEFT,
242 | x0 + w50 + iTextWidth + 2,
243 | yMax - iCursorHeight,
244 | w50 - iTextWidth - 2,
245 | iCursorHeight,
246 | hTab,
247 | NULL,
248 | g_hMainInstance,
249 | NULL);
250 |
251 | ISNULL_GOTO(hEditCommand, error_return);
252 |
253 | // The bottom tab control
254 | hTabBottom = CreateWindow(
255 | WC_TABCONTROL,
256 | NULL,
257 | WS_CHILD | WS_BORDER | WS_VISIBLE,
258 | x0,
259 | y0 + h75,
260 | w50,
261 | h25,
262 | hTab,
263 | (HMENU)IDC_TAB_BOTTOM,
264 | g_hMainInstance,
265 | NULL);
266 | ISNULL_GOTO(hTabBottom, error_return);
267 |
268 | pstTabPageInfo->hMainTab = hTab;
269 | pstTabPageInfo->hEditDisass = hEditDisass;
270 | pstTabPageInfo->hListCallStack = hListCStack;
271 | pstTabPageInfo->hListRegisters = hListRegisters;
272 | pstTabPageInfo->hListThreads = hListThreads;
273 | pstTabPageInfo->hEditCommand = hEditCommand;
274 | pstTabPageInfo->hStaticCommand = hStaticCommand;
275 | pstTabPageInfo->hTabBottom = hTabBottom;
276 | pstTabPageInfo->iTabIndex = iNewIndex;
277 | pstTabPageInfo->hFixedFont = hFixedFont;
278 |
279 | return TRUE;
280 |
281 | error_return:
282 | SET_ERRORCODE_PTR(pdwErrCode);
283 | ZeroMemory(pstTabPageInfo, sizeof(TABPAGEINFO));
284 | return FALSE;
285 | }
286 |
287 | BOOL fInsertTabItem(HWND hTab, WCHAR *pszText, __out int *piNewIndex, __out DWORD *pdwErrCode)
288 | {
289 | ASSERT(hTab);
290 |
291 | int nTabs;
292 | int iNewIndex;
293 | TCITEM tcItem;
294 |
295 | // First, get the number of items(pages) already in tab
296 | nTabs = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
297 |
298 | // Setup the TCITEM structure
299 | ZeroMemory(&tcItem, sizeof(TCITEM));
300 |
301 | if(!ISNULL(pszText))
302 | {
303 | tcItem.mask = TCIF_TEXT;
304 | tcItem.pszText = pszText;
305 | }
306 |
307 | // Insert the item
308 | iNewIndex = SendMessage(hTab, TCM_INSERTITEM, nTabs + 1, (LPARAM)&tcItem);
309 | if(iNewIndex == -1)
310 | {
311 | SET_ERRORCODE_PTR(pdwErrCode);
312 | return FALSE;
313 | }
314 |
315 | if(piNewIndex)
316 | {
317 | *piNewIndex = iNewIndex;
318 | }
319 | return TRUE;
320 | }
321 |
322 | void vDeleteTabPage(HWND hTab, PTABPAGEINFO pstTabPageInfo)
323 | {
324 | ASSERT(ISVALID_HANDLE(hTab));
325 | ASSERT(pstTabPageInfo);
326 | ASSERT(pstTabPageInfo->iTabIndex >= 0);
327 |
328 | // First, destroy all child windows
329 | DestroyWindow(pstTabPageInfo->hEditDisass);
330 | DestroyWindow(pstTabPageInfo->hListCallStack);
331 | DestroyWindow(pstTabPageInfo->hListRegisters);
332 | DestroyWindow(pstTabPageInfo->hListThreads);
333 | DestroyWindow(pstTabPageInfo->hStaticCommand);
334 | DestroyWindow(pstTabPageInfo->hEditCommand);
335 | DestroyWindow(pstTabPageInfo->hTabBottom);
336 |
337 | // Delete the font GDI object
338 | DeleteObject(pstTabPageInfo->hFixedFont);
339 |
340 | // Remove the tab item
341 | SendMessage(hTab, TCM_DELETEITEM, (int)pstTabPageInfo->iTabIndex, (LPARAM)NULL);
342 | }
343 |
344 | BOOL fSetTabPageText(HWND hTab, int iTabIndex, PCWSTR pszTabText)
345 | {
346 | ASSERT(ISVALID_HANDLE(hTab));
347 | ASSERT(iTabIndex >= 0);
348 | ASSERT(pszTabText);
349 |
350 | TCITEM stTcItem = {0};
351 |
352 | stTcItem.mask = TCIF_TEXT;
353 | stTcItem.pszText = (LPWSTR)pszTabText;
354 |
355 | return SendMessage(hTab, TCM_SETITEM, iTabIndex, (LPARAM)&stTcItem);
356 | }
357 |
358 | BOOL fGetFixedWidthFont(HWND hWindow, HFONT *phFont)
359 | {
360 | ASSERT(phFont);
361 |
362 | LOGFONT stLogFont = {0};
363 | struct _FontSelection stFontSel;
364 |
365 | stLogFont.lfCharSet = ANSI_CHARSET;
366 | stLogFont.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
367 | HRESULT hr = StringCchCopy(stLogFont.lfFaceName, LF_FACESIZE, L"Consolas");
368 | if(FAILED(hr))
369 | {
370 | logerror(pstLogger, L"%s(): StringCchCopy() failed %u.", __FUNCTIONW__, GetLastError());
371 | return FALSE;
372 | }
373 |
374 | // 1. EnumFontFamilies to enumerate all styles
375 | int ret = EnumFontFamiliesEx(GetDC(hWindow), &stLogFont, EnumFontCallback, (LPARAM)&stFontSel, 0);
376 | if(ret != 0)
377 | {
378 | logerror(pstLogger, L"%s(): Could not select requested font %u.", __FUNCTIONW__, GetLastError());
379 | return FALSE;
380 | }
381 |
382 | // 2. Populate LOGFONT and call CreateFontIndirect
383 | stFontSel.stLogFont.lfWeight = FW_NORMAL;
384 | stFontSel.stLogFont.lfHeight = -MulDiv(10, GetDeviceCaps(GetDC(hWindow), LOGPIXELSY), 72);
385 | stFontSel.stLogFont.lfWidth = 0;
386 |
387 | HFONT hf = CreateFontIndirect(&stFontSel.stLogFont);
388 | if(!hf)
389 | {
390 | logerror(pstLogger, L"%s(): CreateFontIndirect() failed %u.", __FUNCTIONW__, GetLastError());
391 | return FALSE;
392 | }
393 |
394 | *phFont = hf;
395 | return TRUE;
396 | }
397 |
398 | int CALLBACK EnumFontCallback(
399 | const LOGFONT *lpelfe,
400 | const TEXTMETRIC *lpntme,
401 | DWORD /*FontType*/,
402 | LPARAM lParam)
403 | {
404 | // Select a normal non-italic style
405 | if(lpelfe->lfWeight == FW_NORMAL && lpelfe->lfItalic != TRUE)
406 | {
407 | memcpy(&((struct _FontSelection*)lParam)->stLogFont, lpelfe, sizeof(*lpelfe));
408 | memcpy(&((struct _FontSelection*)lParam)->stTextMetric, lpntme, sizeof(*lpntme));
409 | return 0;
410 | }
411 | return 1;
412 | }
413 |
--------------------------------------------------------------------------------
/Debugger/WndProc.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Inc\WndProc.h"
3 | #include "Inc\DebuggerDP.h"
4 | #include "Inc\MenuItems.h"
5 | #include "Inc\GuiManager.h"
6 | #include "Inc\Debug.h"
7 |
8 | extern PLOGGER pstLogger;
9 | extern HINSTANCE g_hMainInstance;
10 |
11 | static HWND hMainTab = NULL;
12 | static HMENU hMainMenu = NULL;
13 |
14 | static int iConInHandle = -1;
15 | static int iConOutHandle = -1;
16 | static int iConErrHandle = -1;
17 |
18 | static int iCurTabIndex = -1;
19 |
20 | // ** File local funtions **
21 | static BOOL fCreateConsoleWindow();
22 |
23 | // Menu item handlers
24 | static BOOL fStartDebugSession(HWND hMainWindow, struct _DbgSessionStart *pstSessionInfo, __out DWORD *pdwErrCode);
25 |
26 | static BOOL fSendMessageDebugThread(int iCurIndex, DWORD dwMsgToSend, PGUIDBGCOMM pstCommInfo);
27 |
28 |
29 | LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
30 | {
31 | DWORD dwError = ERROR_SUCCESS;
32 |
33 | switch(message)
34 | {
35 | case WM_CREATE:
36 | {
37 | vWriteLog(pstLogger, L"WM_CREATE");
38 |
39 | #if _DEBUG
40 | fCreateConsoleWindow();
41 | #endif
42 |
43 | if(!fCreateMainTabControl(hWnd, &hMainTab, &dwError))
44 | {
45 | vWriteLog(pstLogger, L"%s(): Cannot create main control: %d", __FUNCTIONW__, dwError);
46 | SendMessage(hWnd, WM_CLOSE, 0, 0);
47 | }
48 | else
49 | {
50 | hMainMenu = GetMenu(hWnd);
51 | vMiDebuggerInit(hMainMenu);
52 | }
53 |
54 | if(!fGuiInitialize(&dwError))
55 | {
56 | logerror(pstLogger, L"%s(): Cannot initialize Gui module: %d", __FUNCTIONW__, dwError);
57 | SendMessage(hWnd, WM_CLOSE, 0, 0);
58 | }
59 |
60 | return 0;
61 | }
62 |
63 | case WM_CLOSE:
64 | {
65 | vWriteLog(pstLogger, L"WM_CLOSE");
66 | break;
67 | }
68 |
69 | case WM_DESTROY:
70 | {
71 | vWriteLog(pstLogger, L"WM_DESTROY");
72 | vGuiExit();
73 |
74 | // Terminate logger only at the very end
75 | vTerminateLogger(pstLogger);
76 |
77 | PostQuitMessage(0);
78 | return 0;
79 | }
80 |
81 | case WM_CTLCOLORSTATIC:
82 | {
83 | break;
84 | }
85 |
86 | case WM_NOTIFY:
87 | {
88 | switch(((LPNMHDR)lParam)->code)
89 | {
90 | case TCN_SELCHANGE:
91 | {
92 | iCurTabIndex = TabCtrl_GetCurSel(hMainTab);
93 | if(iCurTabIndex < 0)
94 | {
95 | logwarn(pstLogger, L"%s() %d: TabCtrl_GetCurSel() failed %u", __FUNCTIONW__, __LINE__, GetLastError());
96 | }
97 | return 0;
98 | }
99 | }
100 | break;
101 | }
102 |
103 | case WM_KEYDOWN:
104 | {
105 | // Handling Ctrl+Alt+O. I don't know why accelerator does not work
106 | // for this key combination
107 | if((WORD)wParam == 'O')
108 | {
109 | // Handle this key combination only if the menu item is enabled
110 | int iMenuState = GetMenuState(hMainMenu, IDM_DEBUGPROCESS, MF_BYCOMMAND);
111 |
112 | if(iMenuState != -1 && !(iMenuState & (MF_DISABLED|MF_GRAYED)))
113 | {
114 | int ic = GetKeyState(VK_CONTROL);
115 | int ia = GetKeyState(VK_MENU);
116 |
117 | if(ic < 0 && ia < 0)
118 | {
119 | SendMessage(hWnd, WM_COMMAND, IDM_DEBUGPROCESS, NULL);
120 | }
121 | }
122 | }
123 |
124 | // TODO: Ctrl+Alt+Pause is also not working. Keyboard issue?
125 |
126 | break;
127 | }
128 |
129 | case WM_COMMAND:
130 | {
131 | switch(LOWORD(wParam))
132 | {
133 | case IDM_DEBUGPROGRAM:
134 | {
135 | DBG_SESSIONSTART stSessionInfo;
136 |
137 | // Init struct
138 | ZeroMemory(&stSessionInfo, sizeof(stSessionInfo));
139 |
140 | DialogBoxParam(g_hMainInstance, MAKEINTRESOURCE(IDD_OPENPROGRAM), hWnd, fGetNewProgramDP, (LPARAM)&stSessionInfo);
141 | if(stSessionInfo.szTargetPath[0] == 0)
142 | {
143 | logwarn(pstLogger, L"%s(): Did not get target path to debug from dialog box. Last error = %u", __FUNCTIONW__, GetLastError());
144 | }
145 | else
146 | {
147 | fStartDebugSession(hWnd, &stSessionInfo, &dwError);
148 | }
149 | return 0;
150 | }
151 |
152 | case IDM_DEBUGPROCESS:
153 | {
154 | DBG_SESSIONSTART stSessionInfo;
155 |
156 | // Init struct
157 | ZeroMemory(&stSessionInfo, sizeof(stSessionInfo));
158 |
159 | DialogBoxParam(g_hMainInstance, MAKEINTRESOURCE(IDD_GETPROCID), hWnd, fGetProcIdDP, (LPARAM)&stSessionInfo);
160 | if(stSessionInfo.dwTargetPID == 0)
161 | {
162 | logwarn(pstLogger, L"%s(): Did not get PID to debug from dialog box. Last error = %u", __FUNCTIONW__, GetLastError());
163 | }
164 | else
165 | {
166 | fStartDebugSession(hWnd, &stSessionInfo, &dwError);
167 | }
168 | return 0;
169 | }
170 |
171 | case IDM_TERMINATETARGET:
172 | {
173 | // TODO: handle error return. show MessageBox?
174 | fSendMessageDebugThread(iCurTabIndex, GD_SESS_TERM, NULL);
175 | return 0;
176 | }
177 |
178 | case IDM_DETACHFROMTARGET:
179 | {
180 | fSendMessageDebugThread(iCurTabIndex, GD_SESS_DETACH, NULL);
181 | return 0;
182 | }
183 |
184 | case IDM_DUMPANDTERMINATETARGET:
185 | {
186 | fSendMessageDebugThread(iCurTabIndex, GD_SESS_DUMPTERM, NULL);
187 | return 0;
188 | }
189 |
190 | case IDM_EXITDEBUGGER:
191 | {
192 | vWriteLog(pstLogger, L"IDM_EXITDEBUGGER");
193 |
194 | // TODO: detach/terminate from all targets being debugged
195 |
196 | if(!fOnExitDetachTargets())
197 | {
198 | MessageBox(hWnd, L"Error detaching from targets. See log file.", L"Error", MB_ICONEXCLAMATION|MB_OK);
199 | }
200 |
201 | SendMessage(hWnd, WM_CLOSE, 0, 0);
202 | return 0;
203 | }
204 |
205 | case IDM_CONTINUE:
206 | {
207 | fSendMessageDebugThread(iCurTabIndex, GD_MENU_CONTINUE, NULL);
208 | return 0;
209 | }
210 |
211 | case IDM_STEPINTO:
212 | {
213 | fSendMessageDebugThread(iCurTabIndex, GD_MENU_STEPINTO, NULL);
214 | return 0;
215 | }
216 |
217 | case IDM_BREAKINTOTARGET:
218 | {
219 | logtrace(pstLogger, L"IDM_BREAKINTOTARGET");
220 | fSendMessageDebugThread(iCurTabIndex, GD_MENU_BREAKALL, NULL);
221 | return 0;
222 | }
223 |
224 | case IDM_SUSPENDALLTHREADS:
225 | {
226 | fSendMessageDebugThread(iCurTabIndex, GD_MENU_SUSPALL, NULL);
227 | return 0;
228 | }
229 |
230 | case IDM_RESUMEALLTHREADS:
231 | {
232 | fSendMessageDebugThread(iCurTabIndex, GD_MENU_RESALL, NULL);
233 | return 0;
234 | }
235 |
236 | }// switch(LOWORD...)
237 |
238 | break;
239 |
240 | }// case WM_COMMAND
241 |
242 | // ****************************** Messages from Debug thread ******************************
243 | case DG_SESS_TERM:
244 | {
245 | PGUIDBGCOMM pstDbgComm = (PGUIDBGCOMM)lParam;
246 |
247 | ASSERT(pstDbgComm);
248 |
249 | logtrace(pstLogger, L"%s(): DG_SESS_TERM from thread %u", __FUNCTIONW__, pstDbgComm->dwThreadID);
250 | if(!fGuiRemTab((int)wParam, &dwError))
251 | {
252 | logwarn(pstLogger, L"%s(): fGuiRemTab() failed to remove index %d %u", (int)wParam, dwError);
253 | }
254 |
255 | // Continue even if we failed to remove from hash table (next time we insert, it will simply get overwritten)
256 | vDeleteTabPage(hMainTab, &pstDbgComm->stTabPageInfo);
257 |
258 | FREEIF_GUIDBGCOMM(pstDbgComm);
259 |
260 | return 0;
261 | }
262 |
263 | }
264 |
265 | return DefWindowProc(hWnd, message, wParam, lParam);
266 | }
267 |
268 | static BOOL fStartDebugSession(HWND hMainWindow, struct _DbgSessionStart *pstSessionInfo, __out DWORD *pdwErrCode)
269 | {
270 | ASSERT(ISVALID_HANDLE(hMainWindow));
271 | ASSERT(pstSessionInfo);
272 |
273 | DWORD dwErrorCode = ERROR_SUCCESS;
274 | WCHAR szLogMessage[SLEN_LOGLINE];
275 |
276 | HANDLE hEventInitSync = NULL;
277 | WCHAR szEventNameSync[SLEN_EVENTNAMES];
278 | PDEBUGINFO pDebugInfo = NULL;
279 |
280 | HANDLE hThreadDebug = NULL;
281 | DWORD dwThreadId = 0;
282 |
283 | DWORD dwWaitResult = WAIT_FAILED;
284 |
285 | if(FAILED(CHL_MmAlloc((void**)&pDebugInfo, sizeof(DEBUGINFO), &dwErrorCode)))
286 | {
287 | swprintf_s(szLogMessage, _countof(szLogMessage), L"%s(): CHL_MmAlloc failed: %u", __FUNCTIONW__, dwErrorCode);
288 | vWriteLog(pstLogger, szLogMessage);
289 | goto error_return;
290 | }
291 |
292 | // Debug thread needs to know whether it is debugging a new program or
293 | // an active process
294 | if(pstSessionInfo->fDebuggingActiveProcess)
295 | {
296 | ASSERT(pstSessionInfo->dwTargetPID > 0);
297 | pDebugInfo->fDebuggingActiveProcess = TRUE;
298 | pDebugInfo->dwProcessID = pstSessionInfo->dwTargetPID;
299 | }
300 | else
301 | {
302 | ASSERT(pstSessionInfo->szTargetPath[0] != 0);
303 | wcscpy_s(pDebugInfo->szTargetPath, _countof(pDebugInfo->szTargetPath), pstSessionInfo->szTargetPath);
304 | }
305 |
306 | // Insert new tab page
307 | if(!fCreateTabPage(hMainTab, &pDebugInfo->stTabPageInfo, &dwErrorCode))
308 | {
309 | swprintf_s(szLogMessage, _countof(szLogMessage), L"%s(): fCreateTabPage failed: %u", __FUNCTIONW__, dwErrorCode);
310 | vWriteLog(pstLogger, szLogMessage);
311 | goto error_return;
312 | }
313 |
314 | iCurTabIndex = pDebugInfo->stTabPageInfo.iTabIndex;
315 |
316 | WCHAR szPIDToDisplay[SLEN_COMMON32];
317 |
318 | PCWSTR pszTabText = NULL;
319 |
320 | if(pstSessionInfo->fDebuggingActiveProcess)
321 | {
322 | swprintf_s(szPIDToDisplay, _countof(szPIDToDisplay), L"PID: %u", pstSessionInfo->dwTargetPID);
323 | pszTabText = szPIDToDisplay;
324 | }
325 | else
326 | {
327 | pszTabText = CHL_SzGetFilenameFromPath(
328 | pstSessionInfo->szTargetPath,
329 | wcsnlen_s(pstSessionInfo->szTargetPath, _countof(pstSessionInfo->szTargetPath)));
330 | }
331 |
332 | fSetTabPageText(hMainTab, pDebugInfo->stTabPageInfo.iTabIndex, pszTabText);
333 |
334 | // Create the init sync event, not signaled to start with
335 | LoadString(g_hMainInstance, IDS_GUIDBG_SYNC, szEventNameSync, _countof(szEventNameSync));
336 | hEventInitSync = CreateEvent(NULL, FALSE, FALSE, szEventNameSync);
337 | if(hEventInitSync == NULL)
338 | {
339 | SET_ERRORCODE(dwErrorCode);
340 | vWriteLog(pstLogger, L"%s(): CreateEvent failed: %u %s", __FUNCTIONW__, dwErrorCode, szEventNameSync);
341 | goto error_return;
342 | }
343 |
344 | // Create the debug thread, pass in the required info
345 | pDebugInfo->hMainWindow = hMainWindow;
346 | pDebugInfo->hMainMenu = hMainMenu;
347 | pDebugInfo->fBreakAtMain = pstSessionInfo->fBreakAtMain;
348 | wcscpy_s(pDebugInfo->szInitSyncEvtName, _countof(pDebugInfo->szInitSyncEvtName), szEventNameSync);
349 |
350 | if( (hThreadDebug = CreateThread(NULL, 0, dwDebugThreadEntry, (LPVOID)pDebugInfo, CREATE_SUSPENDED, &dwThreadId)) == NULL )
351 | {
352 | SET_ERRORCODE(dwErrorCode);
353 | vWriteLog(pstLogger, L"%s(): CreateEvent failed: %u %s", __FUNCTIONW__, dwErrorCode, szEventNameSync);
354 | goto error_return;
355 | }
356 |
357 | // Add into map
358 | if(!fGuiAddTab(iCurTabIndex, dwThreadId, &dwErrorCode))
359 | {
360 | logerror(pstLogger, L"Could not insert into tab-thread map: %u", dwErrorCode);
361 | TerminateThread(hThreadDebug, 0); // safe to terminate since it is anyway not running
362 | FREE_HANDLE(hThreadDebug);
363 | goto error_return;
364 | }
365 |
366 | // todo: handle return value
367 | ResumeThread(hThreadDebug);
368 |
369 | dwWaitResult = WaitForSingleObject(hEventInitSync, 5000);
370 | if( dwWaitResult != WAIT_OBJECT_0 )
371 | {
372 | SET_ERRORCODE(dwErrorCode);
373 | // ASSERT(FALSE);
374 | vWriteLog(pstLogger, L"%s(): Debug thread(id: %u) failed to signal init sync event", __FUNCTIONW__, dwThreadId);
375 | // goto error_return;
376 | }
377 | FREE_HANDLE(hEventInitSync);
378 | vWriteLog(pstLogger, L"%s(): Done...", __FUNCTIONW__);
379 | return TRUE;
380 |
381 | error_return:
382 | FREE_HANDLE(hEventInitSync);
383 | IFPTR_FREE(pDebugInfo);
384 | IFPTR_SETVAL(pdwErrCode, dwErrorCode);
385 | // remove the tab page
386 | return FALSE;
387 | }
388 |
389 | static BOOL fSendMessageDebugThread(int iCurIndex, DWORD dwMsgToSend, PGUIDBGCOMM pstCommInfo)
390 | {
391 | ASSERT(iCurIndex >= 0);
392 | ASSERT(dwMsgToSend >= CUSTOM_GDEVENT_START && dwMsgToSend <= CUSTOM_GDEVENT_END);
393 |
394 | DWORD dwError;
395 | DWORD dwThreadId;
396 |
397 | DBG_UNREFERENCED_PARAMETER(pstCommInfo);
398 |
399 | if(!fGuiFindTab(iCurTabIndex, &dwThreadId, &dwError))
400 | {
401 | logerror(pstLogger, L"Cannot find thread ID for tab index %d", iCurTabIndex);
402 | return FALSE;
403 | }
404 |
405 | return PostThreadMessage(dwThreadId, dwMsgToSend, 0, NULL);
406 | }
407 |
408 | static BOOL fCreateConsoleWindow()
409 | {
410 | BOOL fError = TRUE;
411 |
412 | __try
413 | {
414 | if(!AllocConsole())
415 | {
416 | logerror(pstLogger, L"Could not allocate new console: %d", GetLastError());
417 | }
418 | else
419 | {
420 | // Thanks to: http://dslweb.nwnexus.com/~ast/dload/guicon.htm and MSDN
421 | FILE *fp = NULL;
422 | HANDLE hInputHandle = GetStdHandle(STD_INPUT_HANDLE);
423 | HANDLE hOutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
424 | HANDLE hErrorHandle = GetStdHandle(STD_ERROR_HANDLE);
425 |
426 | if(hInputHandle == INVALID_HANDLE_VALUE || hOutputHandle == INVALID_HANDLE_VALUE ||
427 | hErrorHandle == INVALID_HANDLE_VALUE)
428 | {
429 | __leave;
430 | }
431 |
432 | if( (iConInHandle = _open_osfhandle((intptr_t)hInputHandle, _O_RDONLY|_O_TEXT)) == -1 )
433 | __leave;
434 |
435 | fp = _fdopen( iConInHandle, "r" );
436 | *stdin = *fp;
437 |
438 | if( (iConOutHandle = _open_osfhandle((intptr_t)hOutputHandle, _O_APPEND|_O_TEXT)) == -1 )
439 | __leave;
440 |
441 | fp = _fdopen( iConOutHandle, "w+" );
442 | *stdout = *fp;
443 |
444 | if( (iConErrHandle = _open_osfhandle((intptr_t)hErrorHandle, _O_APPEND|_O_TEXT)) == -1 )
445 | __leave;
446 |
447 | fp = _fdopen( iConErrHandle, "w+" );
448 | *stderr = *fp;
449 |
450 | fError = FALSE;
451 | }
452 | }
453 | __finally
454 | {
455 | if(fError)
456 | {
457 | if(iConInHandle != -1) { _close(iConInHandle); iConInHandle = -1; }
458 | if(iConOutHandle != -1) { _close(iConOutHandle); iConOutHandle = -1; }
459 | if(iConErrHandle != -1) { _close(iConErrHandle); iConErrHandle = -1; }
460 | FreeConsole();
461 | }
462 | }
463 |
464 | return !fError;
465 | }
466 |
--------------------------------------------------------------------------------
/Debugger/GuiManager.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Inc\GuiManager.h"
3 | #include "Inc\WndProc.h"
4 |
5 | extern PLOGGER pstLogger;
6 |
7 | static CHL_HTABLE *pTabThreadMap = NULL;
8 |
9 | // File local functions
10 | static BOOL fDisplayActiveProcesses(HWND hProcIDList, DWORD **paProcIDs, DWORD *pnProcIDs, DWORD *pnItemsShown);
11 |
12 | BOOL fGuiInitialize(__out DWORD *pdwErrCode)
13 | {
14 | DBG_UNREFERENCED_PARAMETER(pdwErrCode);
15 |
16 | if(pTabThreadMap)
17 | {
18 | CHL_DsDestroyHT(pTabThreadMap);
19 | }
20 |
21 | if(FAILED(CHL_DsCreateHT(&pTabThreadMap, CHL_DsGetNearestSizeIndexHT(5), CHL_KT_UINT32, CHL_VT_UINT32, FALSE)))
22 | {
23 | vWriteLog(pstLogger, L"fGuiInitialize(): Cannot create tab thread map");
24 | goto error_return;
25 | }
26 |
27 | ASSERT(pTabThreadMap);
28 | return TRUE;
29 |
30 | error_return:
31 | return FALSE;
32 | }
33 |
34 | void vGuiExit()
35 | {
36 | if(pTabThreadMap)
37 | {
38 | CHL_DsDestroyHT(pTabThreadMap);
39 | }
40 | }
41 |
42 | BOOL fGuiAddTab(int tabIndex, DWORD threadId, __out DWORD *pdwErrCode)
43 | {
44 | ASSERT(pTabThreadMap);
45 | ASSERT(tabIndex >= 0);
46 |
47 | DBG_UNREFERENCED_PARAMETER(pdwErrCode);
48 |
49 | #ifdef _DEBUG
50 | WCHAR szDbgMessage[SLEN_LOGLINE];
51 | swprintf_s(szDbgMessage, _countof(szDbgMessage), L"fGuiAddTab(): %d %u", tabIndex, threadId);
52 | vWriteLog(pstLogger, szDbgMessage);
53 | #endif
54 |
55 | return SUCCEEDED(CHL_DsInsertHT(pTabThreadMap, (PCVOID)tabIndex, sizeof(tabIndex), (PCVOID)threadId, sizeof(threadId)));
56 | }
57 |
58 | BOOL fGuiRemTab(int tabIndex, __out DWORD *pdwErrCode)
59 | {
60 | ASSERT(pTabThreadMap);
61 | ASSERT(tabIndex >= 0);
62 |
63 | DBG_UNREFERENCED_PARAMETER(pdwErrCode);
64 |
65 | #ifdef _DEBUG
66 | WCHAR szDbgMessage[SLEN_LOGLINE];
67 | swprintf_s(szDbgMessage, _countof(szDbgMessage), L"fGuiRemTab(): %d", tabIndex);
68 | vWriteLog(pstLogger, szDbgMessage);
69 | #endif
70 |
71 | return CHL_DsRemoveHT(pTabThreadMap, (PCVOID)tabIndex, sizeof(tabIndex));
72 | }
73 |
74 | BOOL fGuiFindTab(int tabIndex, __out DWORD *pdwThreadId, __out DWORD *pdwErrCode)
75 | {
76 | ASSERT(pTabThreadMap);
77 | ASSERT(tabIndex >= 0);
78 | ASSERT(pdwThreadId);
79 |
80 | DBG_UNREFERENCED_PARAMETER(pdwErrCode);
81 |
82 | DWORD dwThreadId;
83 | int iValSize;
84 |
85 | #ifdef _DEBUG
86 | WCHAR szDbgMessage[SLEN_LOGLINE];
87 | swprintf_s(szDbgMessage, _countof(szDbgMessage), L"fGuiFindTab(): %d", tabIndex);
88 | vWriteLog(pstLogger, szDbgMessage);
89 | #endif
90 |
91 | iValSize = sizeof(dwThreadId);
92 | if(FAILED(CHL_DsFindHT(pTabThreadMap, (PCVOID)tabIndex, sizeof(tabIndex), &dwThreadId, &iValSize, FALSE)))
93 | return FALSE;
94 |
95 | *pdwThreadId = dwThreadId;
96 | return TRUE;
97 | }
98 |
99 | // Function to be called when main window is exiting and we want to detach from
100 | // any targets we have attached to.
101 | //
102 | BOOL fOnExitDetachTargets()
103 | {
104 | CHL_HT_ITERATOR htItr;
105 |
106 | int iTabIndex, keySize, valSize;
107 | DWORD dwThreadId;
108 |
109 | HANDLE hThread = NULL;
110 | DWORD dwWaitStatus;
111 |
112 | BOOL fRetVal = TRUE;
113 |
114 | GUIDBGCOMM stGuiDbgComm;
115 |
116 | if(FAILED(CHL_DsInitIteratorHT(pTabThreadMap, &htItr)))
117 | {
118 | logerror(pstLogger, L"%s(): CHL_DsInitIteratorHT() failed %u", GetLastError());
119 | return FALSE;
120 | }
121 |
122 | logtrace(pstLogger, L"%s(): Iterating through tab list...", __FUNCTIONW__);
123 | keySize = sizeof(iTabIndex);
124 | while(SUCCEEDED(CHL_DsGetNextHT(&htItr, &iTabIndex, &keySize, &dwThreadId, &valSize, FALSE)))
125 | {
126 | ASSERT(keySize == sizeof(int) && valSize == sizeof(DWORD));
127 |
128 | logtrace(pstLogger, L"Retrieved %d %u", iTabIndex, dwThreadId);
129 |
130 | hThread = OpenThread(SYNCHRONIZE, FALSE, dwThreadId);
131 | if(hThread == NULL)
132 | {
133 | fRetVal = FALSE;
134 |
135 | logerror(pstLogger, L"OpenThread() failed %u", GetLastError());
136 | continue;
137 | }
138 |
139 | stGuiDbgComm.fFreeThis = FALSE;
140 | stGuiDbgComm.GD_fDetachOnDebuggerExit = TRUE;
141 |
142 | // Post message and wait for it to terminate
143 | if(!PostThreadMessage(dwThreadId, GD_SESS_DETACH, 0, (LPARAM)&stGuiDbgComm))
144 | {
145 | fRetVal = FALSE;
146 |
147 | logerror(pstLogger, L"PostThreadMessage() failed %u", GetLastError());
148 |
149 | CloseHandle(hThread);
150 | continue;
151 | }
152 |
153 | logtrace(pstLogger, L"Waiting for thread %u to exit", dwThreadId);
154 | dwWaitStatus = WaitForSingleObject(hThread, 5000);
155 | if(dwWaitStatus != WAIT_OBJECT_0)
156 | {
157 | fRetVal = FALSE;
158 |
159 | logwarn(pstLogger, L"Thread %u did not terminate within timeout. Moving on...", dwThreadId);
160 |
161 | // fall through to end of while
162 | }
163 |
164 | CloseHandle(hThread);
165 | }
166 |
167 | return fRetVal;
168 | }
169 |
170 | // fGuiGetOpenFilename()
171 | // Just a wrapper for the GetOpenFileName() API
172 | //
173 | BOOL fGuiGetOpenFilename(HWND hMainWindow, WCHAR *pszFilters, __out WCHAR *pszFilepath, DWORD dwBufSize, __out DWORD *pdwErrCode)
174 | {
175 | ASSERT(ISVALID_HANDLE(hMainWindow));
176 | ASSERT(pszFilters);
177 | ASSERT(pszFilepath);
178 |
179 | DBG_UNREFERENCED_PARAMETER(pdwErrCode);
180 |
181 | OPENFILENAME ofn;
182 |
183 | DWORD dwErrorCode = ERROR_SUCCESS;
184 |
185 | ZeroMemory(&ofn, sizeof(ofn));
186 | ofn.lStructSize = sizeof(OPENFILENAME);
187 | ofn.hwndOwner = hMainWindow;
188 | ofn.lpstrFilter = pszFilters;
189 | ofn.nFilterIndex = 1;
190 |
191 | pszFilepath[0] = 0;
192 | ofn.lpstrFile = pszFilepath;
193 | ofn.nMaxFile = dwBufSize;
194 | ofn.Flags = OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_NONETWORKBUTTON;
195 |
196 | if(!GetOpenFileName(&ofn))
197 | {
198 | dwErrorCode = CommDlgExtendedError();
199 | goto error_return;
200 | }
201 | return TRUE;
202 |
203 | error_return:
204 | pszFilepath[0] = 0;
205 | IFPTR_SETVAL(pdwErrCode, dwErrorCode);
206 | return FALSE;
207 | }
208 |
209 | // fGetProcIdDP()
210 | //
211 | BOOL CALLBACK fGetProcIdDP(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
212 | {
213 | static HWND hProcIDList;
214 | static DWORD *paProcIDs;
215 | static DWORD nProcIDs;
216 | static DWORD nListItems;
217 |
218 | static PDBG_SESSIONSTART pstSessionInfo = NULL;
219 |
220 | static int iSelectedListItem;
221 | LPNMLISTVIEW lpNMListView = NULL;
222 |
223 | switch(message)
224 | {
225 | case WM_INITDIALOG:
226 | {
227 | LVCOLUMN lvColumn = {0};
228 |
229 | paProcIDs = NULL;
230 | nProcIDs = 0;
231 | iSelectedListItem = -1;
232 |
233 | // We should get the address where to store the PID chosen by user, from main window
234 | ASSERT(lParam);
235 | pstSessionInfo = (PDBG_SESSIONSTART)lParam;
236 |
237 | // Set flag to indicate that we will debug an active process
238 | pstSessionInfo->fDebuggingActiveProcess = TRUE;
239 |
240 | CHL_GuiCenterWindow(hDlg);
241 |
242 | hProcIDList = GetDlgItem(hDlg, IDC_LIST_PROCIDS);
243 |
244 | // List view headers
245 | lvColumn.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
246 |
247 | // first column
248 | lvColumn.pszText = L"Index";
249 | lvColumn.cx = 0x30;
250 | SendMessage(hProcIDList, LVM_INSERTCOLUMN, 0, (LPARAM)&lvColumn);
251 |
252 | // second column
253 | lvColumn.pszText = L"Process ID";
254 | lvColumn.cx = 0x60;
255 | SendMessage(hProcIDList, LVM_INSERTCOLUMN, 1, (LPARAM)&lvColumn);
256 |
257 | // third column
258 | lvColumn.pszText = L"Process Name";
259 | lvColumn.cx = 0x90;
260 | SendMessage(hProcIDList, LVM_INSERTCOLUMN, 2, (LPARAM)&lvColumn);
261 |
262 | // populate list with active processes' ID
263 | if(!fDisplayActiveProcesses(hProcIDList, &paProcIDs, &nProcIDs, &nListItems))
264 | {
265 | MessageBox(hDlg, L"Cannot display active processes", L"Error", MB_ICONERROR);
266 | SendMessage(hDlg, WM_CLOSE, 0, 0);
267 | }
268 |
269 | return TRUE;
270 | }
271 |
272 | case WM_COMMAND:
273 | {
274 | // handle command sent from child window controls
275 | switch(LOWORD(wParam))
276 | {
277 | case IDB_OPENPROC:
278 | {
279 | if(iSelectedListItem < 0 || iSelectedListItem > nListItems)
280 | {
281 | MessageBox(hDlg, L"You did not select a process to debug", L"No Process", MB_ICONMASK);
282 | }
283 | else
284 | {
285 | LVITEM lvSelItem = {0};
286 | WCHAR wsProcID[11];
287 |
288 | lvSelItem.iItem = iSelectedListItem;
289 | lvSelItem.iSubItem = 1;
290 | lvSelItem.mask = LVIF_TEXT;
291 | lvSelItem.pszText = wsProcID;
292 | lvSelItem.cchTextMax = _countof(wsProcID);
293 |
294 | if(!SendDlgItemMessage(hDlg, IDC_LIST_PROCIDS, LVM_GETITEM, 0, (LPARAM)&lvSelItem))
295 | {
296 | MessageBox(hDlg, L"Error retrieving selected process's PID", L"Error", MB_OK);
297 | pstSessionInfo->dwTargetPID = 0;
298 | }
299 | else
300 | {
301 | pstSessionInfo->dwTargetPID = _wtoi(lvSelItem.pszText);
302 | }
303 |
304 | SendMessage(hDlg, WM_CLOSE, 0, 0);
305 | }
306 | return TRUE;
307 | }
308 |
309 | case IDB_REFRESH:
310 | {
311 | iSelectedListItem = -1;
312 | // populate list with active processes' ID
313 | if(!fDisplayActiveProcesses(hProcIDList, &paProcIDs, &nProcIDs, &nListItems))
314 | {
315 | MessageBox(hDlg, L"Cannot display active processes", L"Error", MB_ICONERROR);
316 | SendMessage(hDlg, WM_CLOSE, 0, 0);
317 | }
318 | return TRUE;
319 | }
320 |
321 | case IDB_CANCEL:
322 | {
323 | SendMessage(hDlg, WM_CLOSE, 0, 0);
324 | return TRUE;
325 | }
326 | }
327 |
328 | break;
329 |
330 | }// WM_COMMAND
331 |
332 | case WM_NOTIFY:
333 | {
334 | switch ( ((LPNMHDR)lParam)->code )
335 | {
336 | case LVN_ITEMCHANGED:
337 | {
338 | if( (lpNMListView = (LPNMLISTVIEW)lParam) == NULL )
339 | {
340 | // error
341 | dbgwprintf(L"%s(): LVN_ITEMCHANGED: lParam is NULL\n", __FUNCTIONW__);
342 | return 0;
343 | }
344 |
345 | if( lpNMListView->uNewState & LVIS_SELECTED )
346 | if( lpNMListView->iItem != -1 )
347 | iSelectedListItem = lpNMListView->iItem;
348 |
349 | return 0; // actually, no return value is required
350 | }
351 | }
352 |
353 | break;
354 |
355 | }// WM_NOTIFY
356 |
357 | case WM_CLOSE:
358 | {
359 | if(paProcIDs)
360 | {
361 | CHL_MmFree((void**)&paProcIDs);
362 | }
363 |
364 | EndDialog(hDlg, 0);
365 | return TRUE;
366 | }
367 |
368 | }
369 | return FALSE;
370 | }// fGetProcIdDP()
371 |
372 | // fDisplayActiveProcesses()
373 | //
374 | static BOOL fDisplayActiveProcesses(HWND hProcIDList, DWORD **paProcIDs, DWORD *pnProcIDs, DWORD *pnItemsShown)
375 | {
376 | ASSERT(hProcIDList && hProcIDList != INVALID_HANDLE_VALUE);
377 |
378 | DWORD dwBytesReturned = 0;
379 | LVITEM lvItem;
380 |
381 | WCHAR wsIndex[5];
382 | WCHAR wsProcID[11];
383 | WCHAR wsProcName[MAX_PATH+1];
384 |
385 | int iRetVal = 0;
386 | int nItemsShown = -1;
387 |
388 | BOOL fErrorInDisplaying = FALSE;
389 |
390 | if(FAILED(CHL_MmAlloc((void**)paProcIDs, 1024*sizeof(DWORD), NULL)))
391 | {
392 | logerror(pstLogger, L"fDisplayActiveProcesses(): mem alloc failed");
393 | return FALSE;
394 | }
395 | ZeroMemory(*paProcIDs, 1024*sizeof(DWORD));
396 |
397 | // Clear list view
398 | if(!SendMessage(hProcIDList, LVM_DELETEALLITEMS, 0, 0))
399 | return FALSE;
400 |
401 | // list processes in the system
402 | if(!EnumProcesses(*paProcIDs, 1024*sizeof(DWORD), &dwBytesReturned))
403 | {
404 | logerror(pstLogger, L"Failed to enumerate processes in the system. Sorry. %d", GetLastError());
405 | return FALSE;
406 | }
407 |
408 | logtrace(pstLogger, L"Enumerated %d processes", dwBytesReturned/sizeof(DWORD));
409 |
410 | *pnProcIDs = dwBytesReturned/sizeof(DWORD);
411 | for(DWORD index = 0; index < dwBytesReturned/sizeof(DWORD); ++index)
412 | {
413 | if(FAILED(CHL_PsGetProcNameFromID((*paProcIDs)[index], wsProcName, _countof(wsProcName))))
414 | {
415 | dbgwprintf(L"Error reading proc name for %d %d\n", (*paProcIDs)[index], GetLastError());
416 | logwarn(pstLogger, L"Error reading proc name for %d %d", (*paProcIDs)[index], GetLastError());
417 | continue;
418 | }
419 | else
420 | {
421 | logtrace(pstLogger, L"%5d %s", (*paProcIDs)[index], wsProcName);
422 | }
423 |
424 | // insert into the list
425 | ZeroMemory(&lvItem, sizeof(lvItem));
426 |
427 | ++nItemsShown;
428 |
429 | // index
430 | swprintf_s(wsIndex, _countof(wsIndex), L"%d", index);
431 | lvItem.iItem = nItemsShown;
432 | lvItem.mask = LVIF_TEXT;
433 | lvItem.pszText = wsIndex;
434 | lvItem.cchTextMax = wcsnlen_s(wsIndex, _countof(wsIndex)) + 1;
435 | if( (iRetVal = SendMessage(hProcIDList, LVM_INSERTITEM, 0, (LPARAM)&lvItem)) == -1 )
436 | {
437 | // error
438 | iRetVal = GetLastError();
439 | logerror(pstLogger, L"fDisplayActiveProcesses(): List insert failed %d", iRetVal);
440 | fErrorInDisplaying = TRUE;
441 | break;
442 | }
443 |
444 | // proc ID
445 | swprintf_s(wsProcID, _countof(wsProcID), L"%d", (*paProcIDs)[index]);
446 | lvItem.iSubItem = 1;
447 | lvItem.mask = LVIF_TEXT;
448 | lvItem.pszText = wsProcID;
449 | lvItem.cchTextMax = wcsnlen_s(wsProcID, _countof(wsProcID)) + 1;
450 | if( (iRetVal = SendMessage(hProcIDList, LVM_SETITEM, 0, (LPARAM)&lvItem)) == -1 )
451 | {
452 | // error
453 | iRetVal = GetLastError();
454 | logerror(pstLogger, L"fDisplayActiveProcesses(): List insert failed %d", iRetVal);
455 | fErrorInDisplaying = TRUE;
456 | break;
457 | }
458 |
459 | // proc name
460 | lvItem.iSubItem = 2;
461 | lvItem.mask = LVIF_TEXT;
462 | lvItem.pszText = wsProcName;
463 | lvItem.cchTextMax = wcsnlen_s(wsProcName, _countof(wsProcName)) + 1;
464 | if( (iRetVal = SendMessage(hProcIDList, LVM_SETITEM, 0, (LPARAM)&lvItem)) == -1 )
465 | {
466 | // error
467 | iRetVal = GetLastError();
468 | logerror(pstLogger, L"fDisplayActiveProcesses(): List insert failed %d", iRetVal);
469 | fErrorInDisplaying = TRUE;
470 | break;
471 | }
472 | }
473 |
474 | *pnItemsShown = nItemsShown;
475 | return !fErrorInDisplaying;
476 |
477 | }// fDisplayActiveProcesses()
478 |
479 | // fGetNewProgramDP()
480 | //
481 | BOOL CALLBACK fGetNewProgramDP(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
482 | {
483 | static PDBG_SESSIONSTART pstSessionInfo = NULL;
484 | static WCHAR szFilters[] = L"Executables\0*.exe\0\0";
485 |
486 | HANDLE hFile = NULL;
487 | WCHAR szTargetPath[SLEN_MAXPATH];
488 |
489 | DWORD dwError = ERROR_SUCCESS;
490 |
491 | switch(message)
492 | {
493 | case WM_INITDIALOG:
494 | {
495 | // We should, from main window, get the address where to store the path of target chosen by user
496 | ASSERT(lParam);
497 | pstSessionInfo = (PDBG_SESSIONSTART)lParam;
498 | ZeroMemory(pstSessionInfo, sizeof(DBG_SESSIONSTART));
499 |
500 | CHL_GuiCenterWindow(hDlg);
501 |
502 | return TRUE;
503 | }
504 |
505 | case WM_COMMAND:
506 | {
507 | // handle command sent from child window controls
508 | switch(LOWORD(wParam))
509 | {
510 | case IDC_NP_BROWSE:
511 | {
512 | // Get the path to the target program to be debugged
513 | if(!fGuiGetOpenFilename(hDlg, szFilters, szTargetPath, sizeof(szTargetPath), &dwError))
514 | {
515 | vWriteLog(pstLogger, L"%s(): fGuiGetOpenFilename failed: %u", __FUNCTIONW__, dwError);
516 | return 0;
517 | }
518 |
519 | // Check if the image file exists and can be read
520 | hFile = CreateFile(szTargetPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
521 | if(hFile == INVALID_HANDLE_VALUE)
522 | {
523 | MessageBox(hDlg, L"Chosen target path not found or access denied. See log file.", L"Error", MB_ICONEXCLAMATION);
524 |
525 | SET_ERRORCODE(dwError);
526 | vWriteLog(pstLogger, L"%s(): CreateFile failed: %u", __FUNCTIONW__, dwError);
527 | return 0;
528 | }
529 | CloseHandle(hFile);
530 |
531 | // Insert path into the edit control
532 | SendDlgItemMessage(hDlg, IDC_NP_PROGRAMPATH, WM_SETTEXT, 0, (LPARAM)szTargetPath);
533 |
534 | return TRUE;
535 | }
536 |
537 | case IDC_NP_OK:
538 | {
539 | // Get the text from edit control
540 | int nLen = SendDlgItemMessage(hDlg, IDC_NP_PROGRAMPATH, WM_GETTEXTLENGTH, 0, NULL);
541 |
542 | if(nLen < 0)
543 | {
544 | // TODO: show error. log it.
545 |
546 | // Close the dialog
547 | ZeroMemory(pstSessionInfo, sizeof(DBG_SESSIONSTART));
548 | SendMessage(hDlg, WM_CLOSE, 0, 0);
549 | }
550 | else if(nLen == 0)
551 | {
552 | MessageBox(hDlg, L"Specify path or click Cancel", L"Info", MB_ICONEXCLAMATION);
553 | }
554 | else if(nLen > SLEN_MAXPATH - 1)
555 | {
556 | MessageBox(hDlg, L"Path too long!", L"Error", MB_ICONEXCLAMATION);
557 | logwarn(pstLogger, L"%s(): Target path length too long %d/%d", __FUNCTIONW__, nLen, SLEN_MAXPATH-1);
558 | }
559 | else
560 | {
561 | // Returns number of chars copied
562 | nLen = SendDlgItemMessage(hDlg, IDC_NP_PROGRAMPATH, WM_GETTEXT, _countof(pstSessionInfo->szTargetPath), (LPARAM)pstSessionInfo->szTargetPath);
563 | if(nLen <= 0)
564 | {
565 | MessageBox(hDlg, L"Error reading specified target path. See log file.", L"Error", MB_ICONERROR);
566 | logwarn(pstLogger, L"%s(): WM_GETTEXT failed %u", __FUNCTIONW__, GetLastError());
567 | }
568 | else
569 | {
570 | // We have copied the path, now get state of the checkbox
571 | if(SendDlgItemMessage(hDlg, IDC_NP_BREAKMAIN, BM_GETCHECK, 0, 0) == BST_CHECKED)
572 | {
573 | pstSessionInfo->fBreakAtMain = TRUE;
574 | }
575 |
576 | SendMessage(hDlg, WM_CLOSE, 0, 0);
577 | }
578 | }
579 | return TRUE;
580 | }
581 |
582 | case IDC_NP_CANCEL:
583 | {
584 | ZeroMemory(pstSessionInfo, sizeof(DBG_SESSIONSTART));
585 | SendMessage(hDlg, WM_CLOSE, 0, 0);
586 | return TRUE;
587 | }
588 | }
589 |
590 | break;
591 |
592 | }// WM_COMMAND
593 |
594 | case WM_CLOSE:
595 | {
596 | EndDialog(hDlg, 0);
597 | return TRUE;
598 | }
599 |
600 | }
601 |
602 | return FALSE;
603 | }
604 |
605 | BOOL fGuiUpdateThreadsList(HWND hThreadListView, PLV_THREADINFO pstLvThreadInfo, int nItems)
606 | {
607 | ASSERT(ISVALID_HANDLE(hThreadListView));
608 | ASSERT(pstLvThreadInfo);
609 | ASSERT(nItems > 0 && nItems < 16000); // a reasonable limit, dont'cha think?
610 |
611 | WCHAR szThreadId[SLEN_INT32];
612 | WCHAR szEipLocation[SLEN_DWORDSTR_HEX];
613 | WCHAR szFunctionName[SLEN_COMMON128];
614 | WCHAR szType[SLEN_COMMON32];
615 | WCHAR szPriority[SLEN_INT32];
616 |
617 | int index;
618 | WCHAR **ppszStrings;
619 |
620 | // Allocate memory to hold WCHAR pointers to the 5 items to display
621 | if(FAILED(CHL_MmAlloc((void**)&ppszStrings, sizeof(WCHAR*) * LV_THREAD_NUMCOLUMNS, NULL)))
622 | {
623 | return FALSE;
624 | }
625 |
626 | static_assert(LV_THREAD_NUMCOLUMNS == 5, "Expected number of list view columns");
627 |
628 | ppszStrings[0] = szThreadId;
629 | ppszStrings[1] = szEipLocation;
630 | ppszStrings[2] = szFunctionName;
631 | ppszStrings[3] = szType;
632 | ppszStrings[4] = szPriority;
633 |
634 | // TODO: log failure as error
635 | ListView_DeleteAllItems(hThreadListView);
636 |
637 | for(index = 0; index < nItems; ++index)
638 | {
639 | // Construct the strings
640 | swprintf_s(szThreadId, _countof(szThreadId), L"%u", pstLvThreadInfo[index].dwThreadId);
641 | swprintf_s(szEipLocation, _countof(szEipLocation), L"0x%08x", pstLvThreadInfo[index].dwEIPLocation);
642 | swprintf_s(szFunctionName, _countof(szFunctionName), L"%s", pstLvThreadInfo[index].szFunction);
643 |
644 | ASSERT(pstLvThreadInfo[index].thType == THTYPE_MAIN || pstLvThreadInfo[index].thType == THTYPE_WORKER);
645 | swprintf_s(szType, _countof(szType), L"%s", aszThreadTypes[pstLvThreadInfo[index].thType]);
646 |
647 | swprintf_s(szPriority, _countof(szPriority), L"%d", pstLvThreadInfo[index].iThreadPri);
648 |
649 | // Insert into list view
650 | if(FAILED(CHL_GuiAddListViewRow(hThreadListView, ppszStrings, LV_THREAD_NUMCOLUMNS, NULL)))
651 | {
652 | logerror(pstLogger, L"%s(): CHL_GuiAddListViewRow failed %u", __FUNCTIONW__, GetLastError());
653 | return FALSE;
654 | }
655 | }
656 |
657 | CHL_MmFree((void**)&ppszStrings);
658 |
659 | return TRUE;
660 | }
661 |
662 | BOOL fGuiUpdateRegistersList(HWND hRegsListView, WCHAR *apszNames[], DWORD *padwValues, int nItems)
663 | {
664 | ASSERT(ISVALID_HANDLE(hRegsListView));
665 | ASSERT(apszNames);
666 | ASSERT(padwValues);
667 | ASSERT(nItems > 0);
668 |
669 | int index;
670 | WCHAR **ppszStrings;
671 |
672 | WCHAR szName[SLEN_REGISTER_NAME];
673 | WCHAR szValue[SLEN_DWORDSTR_HEX];
674 |
675 | // Allocate memory to hold WCHAR pointers to the items to display
676 | if(FAILED(CHL_MmAlloc((void**)&ppszStrings, sizeof(WCHAR*) * LV_REGS_NUMCOLUMNS, NULL)))
677 | {
678 | return FALSE;
679 | }
680 |
681 | static_assert(LV_REGS_NUMCOLUMNS == 2, "Expected number of list view columns");
682 |
683 | ppszStrings[0] = szName;
684 | ppszStrings[1] = szValue;
685 |
686 | // TODO: log failure as error
687 | ListView_DeleteAllItems(hRegsListView);
688 |
689 | for(index = 0; index < nItems; ++index)
690 | {
691 | swprintf_s(szName, _countof(szName), L"%s", apszNames[index]);
692 | swprintf_s(szValue, _countof(szValue), L"0x%08x", padwValues[index]);
693 |
694 | // Insert into list view
695 | if(FAILED(CHL_GuiAddListViewRow(hRegsListView, ppszStrings, LV_REGS_NUMCOLUMNS, NULL)))
696 | {
697 | logerror(pstLogger, L"%s(): CHL_GuiAddListViewRow failed %u", __FUNCTIONW__, GetLastError());
698 | return FALSE;
699 | }
700 | }
701 |
702 | CHL_MmFree((void**)&ppszStrings);
703 |
704 | return TRUE;
705 | }
706 |
--------------------------------------------------------------------------------