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 ()
57 windows_thread_info::suspend ()
62 if (SuspendThread (h
) == (DWORD
) -1)
64 DWORD err
= GetLastError ();
66 /* We get Access Denied (5) when trying to suspend
67 threads that Windows started on behalf of the
68 debuggee, usually when those threads are just
70 We can get Invalid Handle (6) if the main thread
72 if (err
!= ERROR_INVALID_HANDLE
&& err
!= ERROR_ACCESS_DENIED
)
73 warning (_("SuspendThread (tid=0x%x) failed. (winerr %u)"),
74 (unsigned) tid
, (unsigned) err
);
82 windows_thread_info::resume ()
86 stopped_at_software_breakpoint
= false;
88 if (ResumeThread (h
) == (DWORD
) -1)
90 DWORD err
= GetLastError ();
91 warning (_("warning: ResumeThread (tid=0x%x) failed. (winerr %u)"),
92 (unsigned) tid
, (unsigned) err
);
99 get_image_name (HANDLE h
, void *address
, int unicode
)
102 static char buf
[MAX_PATH
];
104 static char buf
[(2 * MAX_PATH
) + 1];
106 DWORD size
= unicode
? sizeof (WCHAR
) : sizeof (char);
112 /* Attempt to read the name of the dll that was detected.
113 This is documented to work only when actively debugging
114 a program. It will not work for attached processes. */
119 /* Windows CE reports the address of the image name,
120 instead of an address of a pointer into the image name. */
121 address_ptr
= address
;
123 /* See if we could read the address of a string, and that the
124 address isn't null. */
125 if (!ReadProcessMemory (h
, address
, &address_ptr
,
126 sizeof (address_ptr
), &done
)
127 || done
!= sizeof (address_ptr
)
132 /* Find the length of the string. */
133 while (ReadProcessMemory (h
, address_ptr
+ len
++ * size
, &b
, size
, &done
)
134 && (b
[0] != 0 || b
[size
- 1] != 0) && done
== size
)
138 ReadProcessMemory (h
, address_ptr
, buf
, len
, &done
);
141 WCHAR
*unicode_address
= (WCHAR
*) alloca (len
* sizeof (WCHAR
));
142 ReadProcessMemory (h
, address_ptr
, unicode_address
, len
* sizeof (WCHAR
),
145 wcstombs (buf
, unicode_address
, MAX_PATH
);
147 WideCharToMultiByte (CP_ACP
, 0, unicode_address
, len
, buf
, sizeof buf
,
155 /* The exception thrown by a program to tell the debugger the name of
156 a thread. The exception record contains an ID of a thread and a
157 name to give it. This exception has no documented name, but MSDN
158 dubs it "MS_VC_EXCEPTION" in one code example. */
159 #define MS_VC_EXCEPTION 0x406d1388
161 handle_exception_result
162 handle_exception (struct target_waitstatus
*ourstatus
, bool debug_exceptions
)
164 #define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \
165 debug_printf ("gdb: Target exception %s at %s\n", x, \
166 host_address_to_string (\
167 current_event.u.Exception.ExceptionRecord.ExceptionAddress))
169 EXCEPTION_RECORD
*rec
= ¤t_event
.u
.Exception
.ExceptionRecord
;
170 DWORD code
= rec
->ExceptionCode
;
171 handle_exception_result result
= HANDLE_EXCEPTION_HANDLED
;
173 memcpy (&siginfo_er
, rec
, sizeof siginfo_er
);
175 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
177 /* Record the context of the current thread. */
178 thread_rec (ptid_t (current_event
.dwProcessId
, current_event
.dwThreadId
, 0),
183 case EXCEPTION_ACCESS_VIOLATION
:
184 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
185 ourstatus
->value
.sig
= GDB_SIGNAL_SEGV
;
186 if (handle_access_violation (rec
))
187 return HANDLE_EXCEPTION_UNHANDLED
;
189 case STATUS_STACK_OVERFLOW
:
190 DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
191 ourstatus
->value
.sig
= GDB_SIGNAL_SEGV
;
193 case STATUS_FLOAT_DENORMAL_OPERAND
:
194 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
195 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
197 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
198 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
199 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
201 case STATUS_FLOAT_INEXACT_RESULT
:
202 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
203 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
205 case STATUS_FLOAT_INVALID_OPERATION
:
206 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
207 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
209 case STATUS_FLOAT_OVERFLOW
:
210 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
211 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
213 case STATUS_FLOAT_STACK_CHECK
:
214 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
215 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
217 case STATUS_FLOAT_UNDERFLOW
:
218 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
219 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
221 case STATUS_FLOAT_DIVIDE_BY_ZERO
:
222 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
223 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
225 case STATUS_INTEGER_DIVIDE_BY_ZERO
:
226 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
227 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
229 case STATUS_INTEGER_OVERFLOW
:
230 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
231 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
233 case EXCEPTION_BREAKPOINT
:
235 if (ignore_first_breakpoint
)
237 /* For WOW64 processes, there are always 2 breakpoint exceptions
238 on startup, first a BREAKPOINT for the 64bit ntdll.dll,
239 then a WX86_BREAKPOINT for the 32bit ntdll.dll.
240 Here we only care about the WX86_BREAKPOINT's. */
241 ourstatus
->kind
= TARGET_WAITKIND_SPURIOUS
;
242 ignore_first_breakpoint
= false;
246 case STATUS_WX86_BREAKPOINT
:
247 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
248 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
250 /* Remove the initial breakpoint. */
251 check_breakpoints ((CORE_ADDR
) (long) current_event
252 .u
.Exception
.ExceptionRecord
.ExceptionAddress
);
256 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
257 ourstatus
->value
.sig
= GDB_SIGNAL_INT
;
259 case DBG_CONTROL_BREAK
:
260 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
261 ourstatus
->value
.sig
= GDB_SIGNAL_INT
;
263 case EXCEPTION_SINGLE_STEP
:
264 case STATUS_WX86_SINGLE_STEP
:
265 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
266 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
268 case EXCEPTION_ILLEGAL_INSTRUCTION
:
269 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
270 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
272 case EXCEPTION_PRIV_INSTRUCTION
:
273 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
274 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
276 case EXCEPTION_NONCONTINUABLE_EXCEPTION
:
277 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
278 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
280 case MS_VC_EXCEPTION
:
281 DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION");
282 if (handle_ms_vc_exception (rec
))
284 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
285 result
= HANDLE_EXCEPTION_IGNORED
;
288 /* treat improperly formed exception as unknown */
291 /* Treat unhandled first chance exceptions specially. */
292 if (current_event
.u
.Exception
.dwFirstChance
)
293 return HANDLE_EXCEPTION_UNHANDLED
;
294 debug_printf ("gdb: unknown target exception 0x%08x at %s\n",
295 (unsigned) current_event
.u
.Exception
.ExceptionRecord
.ExceptionCode
,
296 host_address_to_string (
297 current_event
.u
.Exception
.ExceptionRecord
.ExceptionAddress
));
298 ourstatus
->value
.sig
= GDB_SIGNAL_UNKNOWN
;
302 last_sig
= ourstatus
->value
.sig
;
305 #undef DEBUG_EXCEPTION_SIMPLE
308 /* See nat/windows-nat.h. */
311 matching_pending_stop (bool debug_events
)
313 /* If there are pending stops, and we might plausibly hit one of
314 them, we don't want to actually continue the inferior -- we just
315 want to report the stop. In this case, we just pretend to
316 continue. See the comment by the definition of "pending_stops"
317 for details on why this is needed. */
318 for (const auto &item
: pending_stops
)
320 if (desired_stop_thread_id
== -1
321 || desired_stop_thread_id
== item
.thread_id
)
323 DEBUG_EVENTS (("windows_continue - pending stop anticipated, "
324 "desired=0x%x, item=0x%x\n",
325 desired_stop_thread_id
, item
.thread_id
));
333 /* See nat/windows-nat.h. */
335 gdb::optional
<pending_stop
>
336 fetch_pending_stop (bool debug_events
)
338 gdb::optional
<pending_stop
> result
;
339 for (auto iter
= pending_stops
.begin ();
340 iter
!= pending_stops
.end ();
343 if (desired_stop_thread_id
== -1
344 || desired_stop_thread_id
== iter
->thread_id
)
347 current_event
= iter
->event
;
349 DEBUG_EVENTS (("get_windows_debug_event - "
350 "pending stop found in 0x%x (desired=0x%x)\n",
351 iter
->thread_id
, desired_stop_thread_id
));
353 pending_stops
.erase (iter
);
361 /* See nat/windows-nat.h. */
364 continue_last_debug_event (DWORD continue_status
, bool debug_events
)
366 DEBUG_EVENTS (("ContinueDebugEvent (cpid=%d, ctid=0x%x, %s);\n",
367 (unsigned) last_wait_event
.dwProcessId
,
368 (unsigned) last_wait_event
.dwThreadId
,
369 continue_status
== DBG_CONTINUE
?
370 "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED"));
372 return ContinueDebugEvent (last_wait_event
.dwProcessId
,
373 last_wait_event
.dwThreadId
,
377 /* See nat/windows-nat.h. */
380 wait_for_debug_event (DEBUG_EVENT
*event
, DWORD timeout
)
382 BOOL result
= WaitForDebugEvent (event
, timeout
);
384 last_wait_event
= *event
;