1 /* Internal interfaces for the Windows code
2 Copyright (C) 1995-2020 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 windows_thread_info
*current_windows_thread
;
40 DWORD desired_stop_thread_id
= -1;
41 std::vector
<pending_stop
> pending_stops
;
42 EXCEPTION_RECORD siginfo_er
;
45 bool ignore_first_breakpoint
= false;
48 /* Note that 'debug_events' must be locally defined in the relevant
50 #define DEBUG_EVENTS(x) if (debug_events) debug_printf x
52 windows_thread_info::~windows_thread_info ()
58 windows_thread_info::suspend ()
63 if (SuspendThread (h
) == (DWORD
) -1)
65 DWORD err
= GetLastError ();
67 /* We get Access Denied (5) when trying to suspend
68 threads that Windows started on behalf of the
69 debuggee, usually when those threads are just
71 We can get Invalid Handle (6) if the main thread
73 if (err
!= ERROR_INVALID_HANDLE
&& err
!= ERROR_ACCESS_DENIED
)
74 warning (_("SuspendThread (tid=0x%x) failed. (winerr %u)"),
75 (unsigned) tid
, (unsigned) err
);
83 windows_thread_info::resume ()
87 stopped_at_software_breakpoint
= false;
89 if (ResumeThread (h
) == (DWORD
) -1)
91 DWORD err
= GetLastError ();
92 warning (_("warning: ResumeThread (tid=0x%x) failed. (winerr %u)"),
93 (unsigned) tid
, (unsigned) err
);
100 get_image_name (HANDLE h
, void *address
, int unicode
)
103 static char buf
[MAX_PATH
];
105 static char buf
[(2 * MAX_PATH
) + 1];
107 DWORD size
= unicode
? sizeof (WCHAR
) : sizeof (char);
113 /* Attempt to read the name of the dll that was detected.
114 This is documented to work only when actively debugging
115 a program. It will not work for attached processes. */
120 /* Windows CE reports the address of the image name,
121 instead of an address of a pointer into the image name. */
122 address_ptr
= address
;
124 /* See if we could read the address of a string, and that the
125 address isn't null. */
126 if (!ReadProcessMemory (h
, address
, &address_ptr
,
127 sizeof (address_ptr
), &done
)
128 || done
!= sizeof (address_ptr
)
133 /* Find the length of the string. */
134 while (ReadProcessMemory (h
, address_ptr
+ len
++ * size
, &b
, size
, &done
)
135 && (b
[0] != 0 || b
[size
- 1] != 0) && done
== size
)
139 ReadProcessMemory (h
, address_ptr
, buf
, len
, &done
);
142 WCHAR
*unicode_address
= (WCHAR
*) alloca (len
* sizeof (WCHAR
));
143 ReadProcessMemory (h
, address_ptr
, unicode_address
, len
* sizeof (WCHAR
),
146 wcstombs (buf
, unicode_address
, MAX_PATH
);
148 WideCharToMultiByte (CP_ACP
, 0, unicode_address
, len
, buf
, sizeof buf
,
156 /* The exception thrown by a program to tell the debugger the name of
157 a thread. The exception record contains an ID of a thread and a
158 name to give it. This exception has no documented name, but MSDN
159 dubs it "MS_VC_EXCEPTION" in one code example. */
160 #define MS_VC_EXCEPTION 0x406d1388
162 handle_exception_result
163 handle_exception (struct target_waitstatus
*ourstatus
, bool debug_exceptions
)
165 #define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \
166 debug_printf ("gdb: Target exception %s at %s\n", x, \
167 host_address_to_string (\
168 current_event.u.Exception.ExceptionRecord.ExceptionAddress))
170 EXCEPTION_RECORD
*rec
= ¤t_event
.u
.Exception
.ExceptionRecord
;
171 DWORD code
= rec
->ExceptionCode
;
172 handle_exception_result result
= HANDLE_EXCEPTION_HANDLED
;
174 memcpy (&siginfo_er
, rec
, sizeof siginfo_er
);
176 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
178 /* Record the context of the current thread. */
179 thread_rec (ptid_t (current_event
.dwProcessId
, current_event
.dwThreadId
, 0),
184 case EXCEPTION_ACCESS_VIOLATION
:
185 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
186 ourstatus
->value
.sig
= GDB_SIGNAL_SEGV
;
187 if (handle_access_violation (rec
))
188 return HANDLE_EXCEPTION_UNHANDLED
;
190 case STATUS_STACK_OVERFLOW
:
191 DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
192 ourstatus
->value
.sig
= GDB_SIGNAL_SEGV
;
194 case STATUS_FLOAT_DENORMAL_OPERAND
:
195 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
196 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
198 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
199 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
200 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
202 case STATUS_FLOAT_INEXACT_RESULT
:
203 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
204 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
206 case STATUS_FLOAT_INVALID_OPERATION
:
207 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
208 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
210 case STATUS_FLOAT_OVERFLOW
:
211 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
212 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
214 case STATUS_FLOAT_STACK_CHECK
:
215 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
216 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
218 case STATUS_FLOAT_UNDERFLOW
:
219 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
220 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
222 case STATUS_FLOAT_DIVIDE_BY_ZERO
:
223 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
224 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
226 case STATUS_INTEGER_DIVIDE_BY_ZERO
:
227 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
228 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
230 case STATUS_INTEGER_OVERFLOW
:
231 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
232 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
234 case EXCEPTION_BREAKPOINT
:
236 if (ignore_first_breakpoint
)
238 /* For WOW64 processes, there are always 2 breakpoint exceptions
239 on startup, first a BREAKPOINT for the 64bit ntdll.dll,
240 then a WX86_BREAKPOINT for the 32bit ntdll.dll.
241 Here we only care about the WX86_BREAKPOINT's. */
242 ourstatus
->kind
= TARGET_WAITKIND_SPURIOUS
;
243 ignore_first_breakpoint
= false;
247 case STATUS_WX86_BREAKPOINT
:
248 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
249 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
251 /* Remove the initial breakpoint. */
252 check_breakpoints ((CORE_ADDR
) (long) current_event
253 .u
.Exception
.ExceptionRecord
.ExceptionAddress
);
257 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
258 ourstatus
->value
.sig
= GDB_SIGNAL_INT
;
260 case DBG_CONTROL_BREAK
:
261 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
262 ourstatus
->value
.sig
= GDB_SIGNAL_INT
;
264 case EXCEPTION_SINGLE_STEP
:
265 case STATUS_WX86_SINGLE_STEP
:
266 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
267 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
269 case EXCEPTION_ILLEGAL_INSTRUCTION
:
270 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
271 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
273 case EXCEPTION_PRIV_INSTRUCTION
:
274 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
275 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
277 case EXCEPTION_NONCONTINUABLE_EXCEPTION
:
278 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
279 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
281 case MS_VC_EXCEPTION
:
282 DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION");
283 if (handle_ms_vc_exception (rec
))
285 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
286 result
= HANDLE_EXCEPTION_IGNORED
;
289 /* treat improperly formed exception as unknown */
292 /* Treat unhandled first chance exceptions specially. */
293 if (current_event
.u
.Exception
.dwFirstChance
)
294 return HANDLE_EXCEPTION_UNHANDLED
;
295 debug_printf ("gdb: unknown target exception 0x%08x at %s\n",
296 (unsigned) current_event
.u
.Exception
.ExceptionRecord
.ExceptionCode
,
297 host_address_to_string (
298 current_event
.u
.Exception
.ExceptionRecord
.ExceptionAddress
));
299 ourstatus
->value
.sig
= GDB_SIGNAL_UNKNOWN
;
303 last_sig
= ourstatus
->value
.sig
;
306 #undef DEBUG_EXCEPTION_SIMPLE
309 /* See nat/windows-nat.h. */
312 matching_pending_stop (bool debug_events
)
314 /* If there are pending stops, and we might plausibly hit one of
315 them, we don't want to actually continue the inferior -- we just
316 want to report the stop. In this case, we just pretend to
317 continue. See the comment by the definition of "pending_stops"
318 for details on why this is needed. */
319 for (const auto &item
: pending_stops
)
321 if (desired_stop_thread_id
== -1
322 || desired_stop_thread_id
== item
.thread_id
)
324 DEBUG_EVENTS (("windows_continue - pending stop anticipated, "
325 "desired=0x%x, item=0x%x\n",
326 desired_stop_thread_id
, item
.thread_id
));
334 /* See nat/windows-nat.h. */
336 gdb::optional
<pending_stop
>
337 fetch_pending_stop (bool debug_events
)
339 gdb::optional
<pending_stop
> result
;
340 for (auto iter
= pending_stops
.begin ();
341 iter
!= pending_stops
.end ();
344 if (desired_stop_thread_id
== -1
345 || desired_stop_thread_id
== iter
->thread_id
)
348 current_event
= iter
->event
;
350 DEBUG_EVENTS (("get_windows_debug_event - "
351 "pending stop found in 0x%x (desired=0x%x)\n",
352 iter
->thread_id
, desired_stop_thread_id
));
354 pending_stops
.erase (iter
);
362 /* See nat/windows-nat.h. */
365 continue_last_debug_event (DWORD continue_status
, bool debug_events
)
367 DEBUG_EVENTS (("ContinueDebugEvent (cpid=%d, ctid=0x%x, %s);\n",
368 (unsigned) last_wait_event
.dwProcessId
,
369 (unsigned) last_wait_event
.dwThreadId
,
370 continue_status
== DBG_CONTINUE
?
371 "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED"));
373 return ContinueDebugEvent (last_wait_event
.dwProcessId
,
374 last_wait_event
.dwThreadId
,
378 /* See nat/windows-nat.h. */
381 wait_for_debug_event (DEBUG_EVENT
*event
, DWORD timeout
)
383 BOOL result
= WaitForDebugEvent (event
, timeout
);
385 last_wait_event
= *event
;