xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/nat/windows-nat.c (revision b2c35e17b976cf7ccd7250c86c6f5e95090ed636)
1 /* Internal interfaces for the Windows code
2    Copyright (C) 1995-2020 Free Software Foundation, Inc.
3 
4    This file is part of GDB.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18 
19 #include "gdbsupport/common-defs.h"
20 #include "nat/windows-nat.h"
21 #include "gdbsupport/common-debug.h"
22 
23 namespace windows_nat
24 {
25 
26 HANDLE current_process_handle;
27 DWORD current_process_id;
28 DWORD main_thread_id;
29 enum gdb_signal last_sig = GDB_SIGNAL_0;
30 DEBUG_EVENT current_event;
31 
32 /* The most recent event from WaitForDebugEvent.  Unlike
33    current_event, this is guaranteed never to come from a pending
34    stop.  This is important because only data from the most recent
35    event from WaitForDebugEvent can be used when calling
36    ContinueDebugEvent.  */
37 static DEBUG_EVENT last_wait_event;
38 
39 DWORD desired_stop_thread_id = -1;
40 std::vector<pending_stop> pending_stops;
41 EXCEPTION_RECORD siginfo_er;
42 
43 #ifdef __x86_64__
44 bool ignore_first_breakpoint = false;
45 #endif
46 
47 /* Note that 'debug_events' must be locally defined in the relevant
48    functions.  */
49 #define DEBUG_EVENTS(x)	if (debug_events) debug_printf x
50 
51 windows_thread_info::~windows_thread_info ()
52 {
53 }
54 
55 void
56 windows_thread_info::suspend ()
57 {
58   if (suspended != 0)
59     return;
60 
61   if (SuspendThread (h) == (DWORD) -1)
62     {
63       DWORD err = GetLastError ();
64 
65       /* We get Access Denied (5) when trying to suspend
66 	 threads that Windows started on behalf of the
67 	 debuggee, usually when those threads are just
68 	 about to exit.
69 	 We can get Invalid Handle (6) if the main thread
70 	 has exited.  */
71       if (err != ERROR_INVALID_HANDLE && err != ERROR_ACCESS_DENIED)
72 	warning (_("SuspendThread (tid=0x%x) failed. (winerr %u)"),
73 		 (unsigned) tid, (unsigned) err);
74       suspended = -1;
75     }
76   else
77     suspended = 1;
78 }
79 
80 void
81 windows_thread_info::resume ()
82 {
83   if (suspended > 0)
84     {
85       stopped_at_software_breakpoint = false;
86 
87       if (ResumeThread (h) == (DWORD) -1)
88 	{
89 	  DWORD err = GetLastError ();
90 	  warning (_("warning: ResumeThread (tid=0x%x) failed. (winerr %u)"),
91 		   (unsigned) tid, (unsigned) err);
92 	}
93     }
94   suspended = 0;
95 }
96 
97 const char *
98 get_image_name (HANDLE h, void *address, int unicode)
99 {
100 #ifdef __CYGWIN__
101   static char buf[MAX_PATH];
102 #else
103   static char buf[(2 * MAX_PATH) + 1];
104 #endif
105   DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
106   char *address_ptr;
107   int len = 0;
108   char b[2];
109   SIZE_T done;
110 
111   /* Attempt to read the name of the dll that was detected.
112      This is documented to work only when actively debugging
113      a program.  It will not work for attached processes.  */
114   if (address == NULL)
115     return NULL;
116 
117 #ifdef _WIN32_WCE
118   /* Windows CE reports the address of the image name,
119      instead of an address of a pointer into the image name.  */
120   address_ptr = address;
121 #else
122   /* See if we could read the address of a string, and that the
123      address isn't null.  */
124   if (!ReadProcessMemory (h, address,  &address_ptr,
125 			  sizeof (address_ptr), &done)
126       || done != sizeof (address_ptr)
127       || !address_ptr)
128     return NULL;
129 #endif
130 
131   /* Find the length of the string.  */
132   while (ReadProcessMemory (h, address_ptr + len++ * size, &b, size, &done)
133 	 && (b[0] != 0 || b[size - 1] != 0) && done == size)
134     continue;
135 
136   if (!unicode)
137     ReadProcessMemory (h, address_ptr, buf, len, &done);
138   else
139     {
140       WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR));
141       ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
142 			 &done);
143 #ifdef __CYGWIN__
144       wcstombs (buf, unicode_address, MAX_PATH);
145 #else
146       WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, sizeof buf,
147 			   0, 0);
148 #endif
149     }
150 
151   return buf;
152 }
153 
154 /* The exception thrown by a program to tell the debugger the name of
155    a thread.  The exception record contains an ID of a thread and a
156    name to give it.  This exception has no documented name, but MSDN
157    dubs it "MS_VC_EXCEPTION" in one code example.  */
158 #define MS_VC_EXCEPTION 0x406d1388
159 
160 handle_exception_result
161 handle_exception (struct target_waitstatus *ourstatus, bool debug_exceptions)
162 {
163 #define DEBUG_EXCEPTION_SIMPLE(x)       if (debug_exceptions) \
164   debug_printf ("gdb: Target exception %s at %s\n", x, \
165     host_address_to_string (\
166       current_event.u.Exception.ExceptionRecord.ExceptionAddress))
167 
168   EXCEPTION_RECORD *rec = &current_event.u.Exception.ExceptionRecord;
169   DWORD code = rec->ExceptionCode;
170   handle_exception_result result = HANDLE_EXCEPTION_HANDLED;
171 
172   memcpy (&siginfo_er, rec, sizeof siginfo_er);
173 
174   ourstatus->kind = TARGET_WAITKIND_STOPPED;
175 
176   /* Record the context of the current thread.  */
177   thread_rec (ptid_t (current_event.dwProcessId, current_event.dwThreadId, 0),
178 	      DONT_SUSPEND);
179 
180   switch (code)
181     {
182     case EXCEPTION_ACCESS_VIOLATION:
183       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
184       ourstatus->value.sig = GDB_SIGNAL_SEGV;
185       if (handle_access_violation (rec))
186 	return HANDLE_EXCEPTION_UNHANDLED;
187       break;
188     case STATUS_STACK_OVERFLOW:
189       DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
190       ourstatus->value.sig = GDB_SIGNAL_SEGV;
191       break;
192     case STATUS_FLOAT_DENORMAL_OPERAND:
193       DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
194       ourstatus->value.sig = GDB_SIGNAL_FPE;
195       break;
196     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
197       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
198       ourstatus->value.sig = GDB_SIGNAL_FPE;
199       break;
200     case STATUS_FLOAT_INEXACT_RESULT:
201       DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
202       ourstatus->value.sig = GDB_SIGNAL_FPE;
203       break;
204     case STATUS_FLOAT_INVALID_OPERATION:
205       DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
206       ourstatus->value.sig = GDB_SIGNAL_FPE;
207       break;
208     case STATUS_FLOAT_OVERFLOW:
209       DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
210       ourstatus->value.sig = GDB_SIGNAL_FPE;
211       break;
212     case STATUS_FLOAT_STACK_CHECK:
213       DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
214       ourstatus->value.sig = GDB_SIGNAL_FPE;
215       break;
216     case STATUS_FLOAT_UNDERFLOW:
217       DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
218       ourstatus->value.sig = GDB_SIGNAL_FPE;
219       break;
220     case STATUS_FLOAT_DIVIDE_BY_ZERO:
221       DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
222       ourstatus->value.sig = GDB_SIGNAL_FPE;
223       break;
224     case STATUS_INTEGER_DIVIDE_BY_ZERO:
225       DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
226       ourstatus->value.sig = GDB_SIGNAL_FPE;
227       break;
228     case STATUS_INTEGER_OVERFLOW:
229       DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
230       ourstatus->value.sig = GDB_SIGNAL_FPE;
231       break;
232     case EXCEPTION_BREAKPOINT:
233 #ifdef __x86_64__
234       if (ignore_first_breakpoint)
235 	{
236 	  /* For WOW64 processes, there are always 2 breakpoint exceptions
237 	     on startup, first a BREAKPOINT for the 64bit ntdll.dll,
238 	     then a WX86_BREAKPOINT for the 32bit ntdll.dll.
239 	     Here we only care about the WX86_BREAKPOINT's.  */
240 	  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
241 	  ignore_first_breakpoint = false;
242 	}
243 #endif
244       /* FALLTHROUGH */
245     case STATUS_WX86_BREAKPOINT:
246       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
247       ourstatus->value.sig = GDB_SIGNAL_TRAP;
248 #ifdef _WIN32_WCE
249       /* Remove the initial breakpoint.  */
250       check_breakpoints ((CORE_ADDR) (long) current_event
251 			 .u.Exception.ExceptionRecord.ExceptionAddress);
252 #endif
253       break;
254     case DBG_CONTROL_C:
255       DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
256       ourstatus->value.sig = GDB_SIGNAL_INT;
257       break;
258     case DBG_CONTROL_BREAK:
259       DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
260       ourstatus->value.sig = GDB_SIGNAL_INT;
261       break;
262     case EXCEPTION_SINGLE_STEP:
263     case STATUS_WX86_SINGLE_STEP:
264       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
265       ourstatus->value.sig = GDB_SIGNAL_TRAP;
266       break;
267     case EXCEPTION_ILLEGAL_INSTRUCTION:
268       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
269       ourstatus->value.sig = GDB_SIGNAL_ILL;
270       break;
271     case EXCEPTION_PRIV_INSTRUCTION:
272       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
273       ourstatus->value.sig = GDB_SIGNAL_ILL;
274       break;
275     case EXCEPTION_NONCONTINUABLE_EXCEPTION:
276       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
277       ourstatus->value.sig = GDB_SIGNAL_ILL;
278       break;
279     case MS_VC_EXCEPTION:
280       DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION");
281       if (handle_ms_vc_exception (rec))
282 	{
283 	  ourstatus->value.sig = GDB_SIGNAL_TRAP;
284 	  result = HANDLE_EXCEPTION_IGNORED;
285 	  break;
286 	}
287 	/* treat improperly formed exception as unknown */
288 	/* FALLTHROUGH */
289     default:
290       /* Treat unhandled first chance exceptions specially.  */
291       if (current_event.u.Exception.dwFirstChance)
292 	return HANDLE_EXCEPTION_UNHANDLED;
293       debug_printf ("gdb: unknown target exception 0x%08x at %s\n",
294 	(unsigned) current_event.u.Exception.ExceptionRecord.ExceptionCode,
295 	host_address_to_string (
296 	  current_event.u.Exception.ExceptionRecord.ExceptionAddress));
297       ourstatus->value.sig = GDB_SIGNAL_UNKNOWN;
298       break;
299     }
300 
301   last_sig = ourstatus->value.sig;
302   return result;
303 
304 #undef DEBUG_EXCEPTION_SIMPLE
305 }
306 
307 /* See nat/windows-nat.h.  */
308 
309 bool
310 matching_pending_stop (bool debug_events)
311 {
312   /* If there are pending stops, and we might plausibly hit one of
313      them, we don't want to actually continue the inferior -- we just
314      want to report the stop.  In this case, we just pretend to
315      continue.  See the comment by the definition of "pending_stops"
316      for details on why this is needed.  */
317   for (const auto &item : pending_stops)
318     {
319       if (desired_stop_thread_id == -1
320 	  || desired_stop_thread_id == item.thread_id)
321 	{
322 	  DEBUG_EVENTS (("windows_continue - pending stop anticipated, "
323 			 "desired=0x%x, item=0x%x\n",
324 			 desired_stop_thread_id, item.thread_id));
325 	  return true;
326 	}
327     }
328 
329   return false;
330 }
331 
332 /* See nat/windows-nat.h.  */
333 
334 gdb::optional<pending_stop>
335 fetch_pending_stop (bool debug_events)
336 {
337   gdb::optional<pending_stop> result;
338   for (auto iter = pending_stops.begin ();
339        iter != pending_stops.end ();
340        ++iter)
341     {
342       if (desired_stop_thread_id == -1
343 	  || desired_stop_thread_id == iter->thread_id)
344 	{
345 	  result = *iter;
346 	  current_event = iter->event;
347 
348 	  DEBUG_EVENTS (("get_windows_debug_event - "
349 			 "pending stop found in 0x%x (desired=0x%x)\n",
350 			 iter->thread_id, desired_stop_thread_id));
351 
352 	  pending_stops.erase (iter);
353 	  break;
354 	}
355     }
356 
357   return result;
358 }
359 
360 /* See nat/windows-nat.h.  */
361 
362 BOOL
363 continue_last_debug_event (DWORD continue_status, bool debug_events)
364 {
365   DEBUG_EVENTS (("ContinueDebugEvent (cpid=%d, ctid=0x%x, %s);\n",
366 		  (unsigned) last_wait_event.dwProcessId,
367 		  (unsigned) last_wait_event.dwThreadId,
368 		  continue_status == DBG_CONTINUE ?
369 		  "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED"));
370 
371   return ContinueDebugEvent (last_wait_event.dwProcessId,
372 			     last_wait_event.dwThreadId,
373 			     continue_status);
374 }
375 
376 /* See nat/windows-nat.h.  */
377 
378 BOOL
379 wait_for_debug_event (DEBUG_EVENT *event, DWORD timeout)
380 {
381   BOOL result = WaitForDebugEvent (event, timeout);
382   if (result)
383     last_wait_event = *event;
384   return result;
385 }
386 
387 }
388