1 // just an attempt to implement D debugger for win32 2 module ddebug.windows.windebug; 3 4 import win32.windows; 5 6 import std.utf; 7 8 version(Windows): 9 10 11 class WinDebugger { 12 this() { 13 } 14 15 STARTUPINFOW _si; 16 PROCESS_INFORMATION _pi; 17 18 bool startDebugging(string exefile, string args) { 19 _stopRequested = false; 20 _si = STARTUPINFOW.init; 21 _si.cb = _si.sizeof; 22 _pi = PROCESS_INFORMATION.init; 23 24 string cmdline = "\"" ~ exefile ~ "\""; 25 if (args.length > 0) 26 cmdline = cmdline ~ " " ~ args; 27 wchar[] exefilew = cast(wchar[])toUTF16(exefile); 28 exefilew ~= cast(dchar)0; 29 wchar[] cmdlinew = cast(wchar[])toUTF16(cmdline); 30 cmdlinew ~= cast(dchar)0; 31 if (!CreateProcessW(cast(const wchar*)exefilew.ptr, 32 cmdlinew.ptr, 33 cast(SECURITY_ATTRIBUTES*)NULL, cast(SECURITY_ATTRIBUTES*)NULL, 34 FALSE, 35 DEBUG_ONLY_THIS_PROCESS, 36 NULL, 37 cast(const wchar*)NULL, &_si, &_pi)) { 38 return false; 39 } 40 return true; 41 } 42 43 uint onCreateThreadDebugEvent(ref DEBUG_EVENT debug_event) { 44 return DBG_CONTINUE; 45 } 46 uint onCreateProcessDebugEvent(ref DEBUG_EVENT debug_event) { 47 return DBG_CONTINUE; 48 } 49 uint onExitThreadDebugEvent(ref DEBUG_EVENT debug_event) { 50 return DBG_CONTINUE; 51 } 52 uint onExitProcessDebugEvent(ref DEBUG_EVENT debug_event) { 53 return DBG_CONTINUE; 54 } 55 uint onLoadDllDebugEvent(ref DEBUG_EVENT debug_event) { 56 return DBG_CONTINUE; 57 } 58 uint onUnloadDllDebugEvent(ref DEBUG_EVENT debug_event) { 59 return DBG_CONTINUE; 60 } 61 uint onOutputDebugStringEvent(ref DEBUG_EVENT debug_event) { 62 return DBG_CONTINUE; 63 } 64 uint onRipEvent(ref DEBUG_EVENT debug_event) { 65 return DBG_TERMINATE_PROCESS; 66 } 67 68 void processDebugEvent(ref DEBUG_EVENT debug_event) { 69 switch (debug_event.dwDebugEventCode) 70 { 71 case EXCEPTION_DEBUG_EVENT: 72 // Process the exception code. When handling 73 // exceptions, remember to set the continuation 74 // status parameter (dwContinueStatus). This value 75 // is used by the ContinueDebugEvent function. 76 77 switch(debug_event.Exception.ExceptionRecord.ExceptionCode) 78 { 79 case EXCEPTION_ACCESS_VIOLATION: 80 // First chance: Pass this on to the system. 81 // Last chance: Display an appropriate error. 82 break; 83 84 case EXCEPTION_BREAKPOINT: 85 // First chance: Display the current 86 // instruction and register values. 87 break; 88 89 case EXCEPTION_DATATYPE_MISALIGNMENT: 90 // First chance: Pass this on to the system. 91 // Last chance: Display an appropriate error. 92 break; 93 94 case EXCEPTION_SINGLE_STEP: 95 // First chance: Update the display of the 96 // current instruction and register values. 97 break; 98 99 case DBG_CONTROL_C: 100 // First chance: Pass this on to the system. 101 // Last chance: Display an appropriate error. 102 break; 103 104 default: 105 // Handle other exceptions. 106 break; 107 } 108 109 break; 110 111 case CREATE_THREAD_DEBUG_EVENT: 112 // As needed, examine or change the thread's registers 113 // with the GetThreadContext and SetThreadContext functions; 114 // and suspend and resume thread execution with the 115 // SuspendThread and ResumeThread functions. 116 117 _continueStatus = onCreateThreadDebugEvent(debug_event); 118 break; 119 120 case CREATE_PROCESS_DEBUG_EVENT: 121 // As needed, examine or change the registers of the 122 // process's initial thread with the GetThreadContext and 123 // SetThreadContext functions; read from and write to the 124 // process's virtual memory with the ReadProcessMemory and 125 // WriteProcessMemory functions; and suspend and resume 126 // thread execution with the SuspendThread and ResumeThread 127 // functions. Be sure to close the handle to the process image 128 // file with CloseHandle. 129 130 _continueStatus = onCreateProcessDebugEvent(debug_event); 131 break; 132 133 case EXIT_THREAD_DEBUG_EVENT: 134 // Display the thread's exit code. 135 136 _continueStatus = onExitThreadDebugEvent(debug_event); 137 break; 138 139 case EXIT_PROCESS_DEBUG_EVENT: 140 // Display the process's exit code. 141 142 _continueStatus = onExitProcessDebugEvent(debug_event); 143 break; 144 145 case LOAD_DLL_DEBUG_EVENT: 146 // Read the debugging information included in the newly 147 // loaded DLL. Be sure to close the handle to the loaded DLL 148 // with CloseHandle. 149 150 _continueStatus = onLoadDllDebugEvent(debug_event); 151 break; 152 153 case UNLOAD_DLL_DEBUG_EVENT: 154 // Display a message that the DLL has been unloaded. 155 156 _continueStatus = onUnloadDllDebugEvent(debug_event); 157 break; 158 159 case OUTPUT_DEBUG_STRING_EVENT: 160 // Display the output debugging string. 161 162 _continueStatus = onOutputDebugStringEvent(debug_event); 163 break; 164 165 case RIP_EVENT: 166 _continueStatus = onRipEvent(debug_event); 167 break; 168 default: 169 // UNKNOWN EVENT 170 break; 171 } 172 } 173 174 uint _continueStatus; 175 bool _stopRequested; 176 177 bool enterDebugLoop() { 178 _continueStatus = DBG_CONTINUE; 179 DEBUG_EVENT debug_event; 180 for(;;) 181 { 182 if (!WaitForDebugEvent(&debug_event, INFINITE)) 183 return false; 184 processDebugEvent(debug_event); 185 ContinueDebugEvent(debug_event.dwProcessId, 186 debug_event.dwThreadId, 187 _continueStatus); 188 } 189 } 190 }