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 }