1 /* Internal interfaces for the Windows code
2 Copyright (C) 1995-2021 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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/>. */
19 #include "gdbsupport/common-defs.h"
20 #include "nat/windows-nat.h"
21 #include "gdbsupport/common-debug.h"
26 HANDLE current_process_handle
;
27 DWORD current_process_id
;
29 enum gdb_signal last_sig
= GDB_SIGNAL_0
;
30 DEBUG_EVENT current_event
;
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
;
39 DWORD desired_stop_thread_id
= -1;
40 std::vector
<pending_stop
> pending_stops
;
41 EXCEPTION_RECORD siginfo_er
;
44 bool wow64_process
= false;
45 bool ignore_first_breakpoint
= false;
48 /* Note that 'debug_events' must be locally defined in the relevant
50 #define DEBUG_EVENTS(fmt, ...) \
51 debug_prefixed_printf_cond (debug_events, "windows events", fmt, \
54 windows_thread_info::~windows_thread_info ()
59 windows_thread_info::suspend ()
64 if (SuspendThread (h
) == (DWORD
) -1)
66 DWORD err
= GetLastError ();
68 /* We get Access Denied (5) when trying to suspend
69 threads that Windows started on behalf of the
70 debuggee, usually when those threads are just
72 We can get Invalid Handle (6) if the main thread
74 if (err
!= ERROR_INVALID_HANDLE
&& err
!= ERROR_ACCESS_DENIED
)
75 warning (_("SuspendThread (tid=0x%x) failed. (winerr %u)"),
76 (unsigned) tid
, (unsigned) err
);
84 windows_thread_info::resume ()
88 stopped_at_software_breakpoint
= false;
90 if (ResumeThread (h
) == (DWORD
) -1)
92 DWORD err
= GetLastError ();
93 warning (_("warning: ResumeThread (tid=0x%x) failed. (winerr %u)"),
94 (unsigned) tid
, (unsigned) err
);
101 get_image_name (HANDLE h
, void *address
, int unicode
)
104 static char buf
[MAX_PATH
];
106 static char buf
[(2 * MAX_PATH
) + 1];
108 DWORD size
= unicode
? sizeof (WCHAR
) : sizeof (char);
114 /* Attempt to read the name of the dll that was detected.
115 This is documented to work only when actively debugging
116 a program. It will not work for attached processes. */
121 /* Windows CE reports the address of the image name,
122 instead of an address of a pointer into the image name. */
123 address_ptr
= address
;
125 /* See if we could read the address of a string, and that the
126 address isn't null. */
127 if (!ReadProcessMemory (h
, address
, &address_ptr
,
128 sizeof (address_ptr
), &done
)
129 || done
!= sizeof (address_ptr
)
134 /* Find the length of the string. */
135 while (ReadProcessMemory (h
, address_ptr
+ len
++ * size
, &b
, size
, &done
)
136 && (b
[0] != 0 || b
[size
- 1] != 0) && done
== size
)
140 ReadProcessMemory (h
, address_ptr
, buf
, len
, &done
);
143 WCHAR
*unicode_address
= (WCHAR
*) alloca (len
* sizeof (WCHAR
));
144 ReadProcessMemory (h
, address_ptr
, unicode_address
, len
* sizeof (WCHAR
),
147 wcstombs (buf
, unicode_address
, MAX_PATH
);
149 WideCharToMultiByte (CP_ACP
, 0, unicode_address
, len
, buf
, sizeof buf
,
157 /* The exception thrown by a program to tell the debugger the name of
158 a thread. The exception record contains an ID of a thread and a
159 name to give it. This exception has no documented name, but MSDN
160 dubs it "MS_VC_EXCEPTION" in one code example. */
161 #define MS_VC_EXCEPTION 0x406d1388
163 handle_exception_result
164 handle_exception (struct target_waitstatus
*ourstatus
, bool debug_exceptions
)
166 #define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \
167 debug_printf ("gdb: Target exception %s at %s\n", x, \
168 host_address_to_string (\
169 current_event.u.Exception.ExceptionRecord.ExceptionAddress))
171 EXCEPTION_RECORD
*rec
= ¤t_event
.u
.Exception
.ExceptionRecord
;
172 DWORD code
= rec
->ExceptionCode
;
173 handle_exception_result result
= HANDLE_EXCEPTION_HANDLED
;
175 memcpy (&siginfo_er
, rec
, sizeof siginfo_er
);
177 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
179 /* Record the context of the current thread. */
180 thread_rec (ptid_t (current_event
.dwProcessId
, current_event
.dwThreadId
, 0),
185 case EXCEPTION_ACCESS_VIOLATION
:
186 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
187 ourstatus
->value
.sig
= GDB_SIGNAL_SEGV
;
188 if (handle_access_violation (rec
))
189 return HANDLE_EXCEPTION_UNHANDLED
;
191 case STATUS_STACK_OVERFLOW
:
192 DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
193 ourstatus
->value
.sig
= GDB_SIGNAL_SEGV
;
195 case STATUS_FLOAT_DENORMAL_OPERAND
:
196 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
197 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
199 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
200 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
201 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
203 case STATUS_FLOAT_INEXACT_RESULT
:
204 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
205 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
207 case STATUS_FLOAT_INVALID_OPERATION
:
208 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
209 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
211 case STATUS_FLOAT_OVERFLOW
:
212 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
213 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
215 case STATUS_FLOAT_STACK_CHECK
:
216 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
217 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
219 case STATUS_FLOAT_UNDERFLOW
:
220 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
221 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
223 case STATUS_FLOAT_DIVIDE_BY_ZERO
:
224 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
225 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
227 case STATUS_INTEGER_DIVIDE_BY_ZERO
:
228 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
229 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
231 case STATUS_INTEGER_OVERFLOW
:
232 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
233 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
235 case EXCEPTION_BREAKPOINT
:
237 if (ignore_first_breakpoint
)
239 /* For WOW64 processes, there are always 2 breakpoint exceptions
240 on startup, first a BREAKPOINT for the 64bit ntdll.dll,
241 then a WX86_BREAKPOINT for the 32bit ntdll.dll.
242 Here we only care about the WX86_BREAKPOINT's. */
243 ourstatus
->kind
= TARGET_WAITKIND_SPURIOUS
;
244 ignore_first_breakpoint
= false;
246 else if (wow64_process
)
248 /* This breakpoint exception is triggered for WOW64 processes when
249 reaching an int3 instruction in 64bit code.
250 gdb checks for int3 in case of SIGTRAP, this fails because
251 Wow64GetThreadContext can only report the pc of 32bit code, and
252 gdb lets the target process continue.
253 So handle it as SIGINT instead, then the target is stopped
255 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
256 rec
->ExceptionCode
= DBG_CONTROL_C
;
257 ourstatus
->value
.sig
= GDB_SIGNAL_INT
;
262 case STATUS_WX86_BREAKPOINT
:
263 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
264 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
266 /* Remove the initial breakpoint. */
267 check_breakpoints ((CORE_ADDR
) (long) current_event
268 .u
.Exception
.ExceptionRecord
.ExceptionAddress
);
272 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
273 ourstatus
->value
.sig
= GDB_SIGNAL_INT
;
275 case DBG_CONTROL_BREAK
:
276 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
277 ourstatus
->value
.sig
= GDB_SIGNAL_INT
;
279 case EXCEPTION_SINGLE_STEP
:
280 case STATUS_WX86_SINGLE_STEP
:
281 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
282 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
284 case EXCEPTION_ILLEGAL_INSTRUCTION
:
285 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
286 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
288 case EXCEPTION_PRIV_INSTRUCTION
:
289 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
290 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
292 case EXCEPTION_NONCONTINUABLE_EXCEPTION
:
293 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
294 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
296 case MS_VC_EXCEPTION
:
297 DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION");
298 if (handle_ms_vc_exception (rec
))
300 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
301 result
= HANDLE_EXCEPTION_IGNORED
;
304 /* treat improperly formed exception as unknown */
307 /* Treat unhandled first chance exceptions specially. */
308 if (current_event
.u
.Exception
.dwFirstChance
)
309 return HANDLE_EXCEPTION_UNHANDLED
;
310 debug_printf ("gdb: unknown target exception 0x%08x at %s\n",
311 (unsigned) current_event
.u
.Exception
.ExceptionRecord
.ExceptionCode
,
312 host_address_to_string (
313 current_event
.u
.Exception
.ExceptionRecord
.ExceptionAddress
));
314 ourstatus
->value
.sig
= GDB_SIGNAL_UNKNOWN
;
318 last_sig
= ourstatus
->value
.sig
;
321 #undef DEBUG_EXCEPTION_SIMPLE
324 /* See nat/windows-nat.h. */
327 matching_pending_stop (bool debug_events
)
329 /* If there are pending stops, and we might plausibly hit one of
330 them, we don't want to actually continue the inferior -- we just
331 want to report the stop. In this case, we just pretend to
332 continue. See the comment by the definition of "pending_stops"
333 for details on why this is needed. */
334 for (const auto &item
: pending_stops
)
336 if (desired_stop_thread_id
== -1
337 || desired_stop_thread_id
== item
.thread_id
)
339 DEBUG_EVENTS ("pending stop anticipated, desired=0x%x, item=0x%x",
340 desired_stop_thread_id
, item
.thread_id
);
348 /* See nat/windows-nat.h. */
350 gdb::optional
<pending_stop
>
351 fetch_pending_stop (bool debug_events
)
353 gdb::optional
<pending_stop
> result
;
354 for (auto iter
= pending_stops
.begin ();
355 iter
!= pending_stops
.end ();
358 if (desired_stop_thread_id
== -1
359 || desired_stop_thread_id
== iter
->thread_id
)
362 current_event
= iter
->event
;
364 DEBUG_EVENTS ("pending stop found in 0x%x (desired=0x%x)",
365 iter
->thread_id
, desired_stop_thread_id
);
367 pending_stops
.erase (iter
);
375 /* See nat/windows-nat.h. */
378 continue_last_debug_event (DWORD continue_status
, bool debug_events
)
380 DEBUG_EVENTS ("ContinueDebugEvent (cpid=%d, ctid=0x%x, %s)",
381 (unsigned) last_wait_event
.dwProcessId
,
382 (unsigned) last_wait_event
.dwThreadId
,
383 continue_status
== DBG_CONTINUE
?
384 "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED");
386 return ContinueDebugEvent (last_wait_event
.dwProcessId
,
387 last_wait_event
.dwThreadId
,
391 /* See nat/windows-nat.h. */
394 wait_for_debug_event (DEBUG_EVENT
*event
, DWORD timeout
)
396 BOOL result
= WaitForDebugEvent (event
, timeout
);
398 last_wait_event
= *event
;