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"
23 #define STATUS_WX86_BREAKPOINT 0x4000001F
24 #define STATUS_WX86_SINGLE_STEP 0x4000001E
29 HANDLE current_process_handle
;
30 DWORD current_process_id
;
32 enum gdb_signal last_sig
= GDB_SIGNAL_0
;
33 DEBUG_EVENT current_event
;
34 DEBUG_EVENT last_wait_event
;
35 windows_thread_info
*current_windows_thread
;
36 DWORD desired_stop_thread_id
= -1;
37 std::vector
<pending_stop
> pending_stops
;
38 EXCEPTION_RECORD siginfo_er
;
40 /* Note that 'debug_events' must be locally defined in the relevant
42 #define DEBUG_EVENTS(x) if (debug_events) debug_printf x
44 windows_thread_info::~windows_thread_info ()
50 windows_thread_info::suspend ()
55 if (SuspendThread (h
) == (DWORD
) -1)
57 DWORD err
= GetLastError ();
59 /* We get Access Denied (5) when trying to suspend
60 threads that Windows started on behalf of the
61 debuggee, usually when those threads are just
63 We can get Invalid Handle (6) if the main thread
65 if (err
!= ERROR_INVALID_HANDLE
&& err
!= ERROR_ACCESS_DENIED
)
66 warning (_("SuspendThread (tid=0x%x) failed. (winerr %u)"),
67 (unsigned) tid
, (unsigned) err
);
75 windows_thread_info::resume ()
79 stopped_at_software_breakpoint
= false;
81 if (ResumeThread (h
) == (DWORD
) -1)
83 DWORD err
= GetLastError ();
84 warning (_("warning: ResumeThread (tid=0x%x) failed. (winerr %u)"),
85 (unsigned) tid
, (unsigned) err
);
92 get_image_name (HANDLE h
, void *address
, int unicode
)
95 static char buf
[MAX_PATH
];
97 static char buf
[(2 * MAX_PATH
) + 1];
99 DWORD size
= unicode
? sizeof (WCHAR
) : sizeof (char);
105 /* Attempt to read the name of the dll that was detected.
106 This is documented to work only when actively debugging
107 a program. It will not work for attached processes. */
112 /* Windows CE reports the address of the image name,
113 instead of an address of a pointer into the image name. */
114 address_ptr
= address
;
116 /* See if we could read the address of a string, and that the
117 address isn't null. */
118 if (!ReadProcessMemory (h
, address
, &address_ptr
,
119 sizeof (address_ptr
), &done
)
120 || done
!= sizeof (address_ptr
)
125 /* Find the length of the string. */
126 while (ReadProcessMemory (h
, address_ptr
+ len
++ * size
, &b
, size
, &done
)
127 && (b
[0] != 0 || b
[size
- 1] != 0) && done
== size
)
131 ReadProcessMemory (h
, address_ptr
, buf
, len
, &done
);
134 WCHAR
*unicode_address
= (WCHAR
*) alloca (len
* sizeof (WCHAR
));
135 ReadProcessMemory (h
, address_ptr
, unicode_address
, len
* sizeof (WCHAR
),
138 wcstombs (buf
, unicode_address
, MAX_PATH
);
140 WideCharToMultiByte (CP_ACP
, 0, unicode_address
, len
, buf
, sizeof buf
,
148 /* The exception thrown by a program to tell the debugger the name of
149 a thread. The exception record contains an ID of a thread and a
150 name to give it. This exception has no documented name, but MSDN
151 dubs it "MS_VC_EXCEPTION" in one code example. */
152 #define MS_VC_EXCEPTION 0x406d1388
154 handle_exception_result
155 handle_exception (struct target_waitstatus
*ourstatus
, bool debug_exceptions
)
157 #define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \
158 debug_printf ("gdb: Target exception %s at %s\n", x, \
159 host_address_to_string (\
160 current_event.u.Exception.ExceptionRecord.ExceptionAddress))
162 EXCEPTION_RECORD
*rec
= ¤t_event
.u
.Exception
.ExceptionRecord
;
163 DWORD code
= rec
->ExceptionCode
;
164 handle_exception_result result
= HANDLE_EXCEPTION_HANDLED
;
166 memcpy (&siginfo_er
, rec
, sizeof siginfo_er
);
168 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
170 /* Record the context of the current thread. */
171 thread_rec (ptid_t (current_event
.dwProcessId
, current_event
.dwThreadId
, 0),
176 case EXCEPTION_ACCESS_VIOLATION
:
177 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
178 ourstatus
->value
.sig
= GDB_SIGNAL_SEGV
;
181 /* See if the access violation happened within the cygwin DLL
182 itself. Cygwin uses a kind of exception handling to deal
183 with passed-in invalid addresses. gdb should not treat
184 these as real SEGVs since they will be silently handled by
185 cygwin. A real SEGV will (theoretically) be caught by
186 cygwin later in the process and will be sent as a
187 cygwin-specific-signal. So, ignore SEGVs if they show up
188 within the text segment of the DLL itself. */
190 CORE_ADDR addr
= (CORE_ADDR
) (uintptr_t) rec
->ExceptionAddress
;
192 if ((!cygwin_exceptions
&& (addr
>= cygwin_load_start
193 && addr
< cygwin_load_end
))
194 || (find_pc_partial_function (addr
, &fn
, NULL
, NULL
)
195 && startswith (fn
, "KERNEL32!IsBad")))
196 return HANDLE_EXCEPTION_UNHANDLED
;
200 case STATUS_STACK_OVERFLOW
:
201 DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
202 ourstatus
->value
.sig
= GDB_SIGNAL_SEGV
;
204 case STATUS_FLOAT_DENORMAL_OPERAND
:
205 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
206 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
208 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
209 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
210 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
212 case STATUS_FLOAT_INEXACT_RESULT
:
213 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
214 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
216 case STATUS_FLOAT_INVALID_OPERATION
:
217 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
218 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
220 case STATUS_FLOAT_OVERFLOW
:
221 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
222 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
224 case STATUS_FLOAT_STACK_CHECK
:
225 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
226 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
228 case STATUS_FLOAT_UNDERFLOW
:
229 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
230 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
232 case STATUS_FLOAT_DIVIDE_BY_ZERO
:
233 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
234 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
236 case STATUS_INTEGER_DIVIDE_BY_ZERO
:
237 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
238 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
240 case STATUS_INTEGER_OVERFLOW
:
241 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
242 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
244 case EXCEPTION_BREAKPOINT
:
246 if (ignore_first_breakpoint
)
248 /* For WOW64 processes, there are always 2 breakpoint exceptions
249 on startup, first a BREAKPOINT for the 64bit ntdll.dll,
250 then a WX86_BREAKPOINT for the 32bit ntdll.dll.
251 Here we only care about the WX86_BREAKPOINT's. */
252 ourstatus
->kind
= TARGET_WAITKIND_SPURIOUS
;
253 ignore_first_breakpoint
= false;
257 case STATUS_WX86_BREAKPOINT
:
258 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
259 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
261 /* Remove the initial breakpoint. */
262 check_breakpoints ((CORE_ADDR
) (long) current_event
263 .u
.Exception
.ExceptionRecord
.ExceptionAddress
);
267 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
268 ourstatus
->value
.sig
= GDB_SIGNAL_INT
;
270 case DBG_CONTROL_BREAK
:
271 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
272 ourstatus
->value
.sig
= GDB_SIGNAL_INT
;
274 case EXCEPTION_SINGLE_STEP
:
275 case STATUS_WX86_SINGLE_STEP
:
276 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
277 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
279 case EXCEPTION_ILLEGAL_INSTRUCTION
:
280 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
281 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
283 case EXCEPTION_PRIV_INSTRUCTION
:
284 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
285 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
287 case EXCEPTION_NONCONTINUABLE_EXCEPTION
:
288 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
289 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
291 case MS_VC_EXCEPTION
:
292 DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION");
293 if (handle_ms_vc_exception (rec
))
295 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
296 result
= HANDLE_EXCEPTION_IGNORED
;
299 /* treat improperly formed exception as unknown */
302 /* Treat unhandled first chance exceptions specially. */
303 if (current_event
.u
.Exception
.dwFirstChance
)
304 return HANDLE_EXCEPTION_UNHANDLED
;
305 debug_printf ("gdb: unknown target exception 0x%08x at %s\n",
306 (unsigned) current_event
.u
.Exception
.ExceptionRecord
.ExceptionCode
,
307 host_address_to_string (
308 current_event
.u
.Exception
.ExceptionRecord
.ExceptionAddress
));
309 ourstatus
->value
.sig
= GDB_SIGNAL_UNKNOWN
;
313 last_sig
= ourstatus
->value
.sig
;
316 #undef DEBUG_EXCEPTION_SIMPLE
319 /* See nat/windows-nat.h. */
322 matching_pending_stop (bool debug_events
)
324 /* If there are pending stops, and we might plausibly hit one of
325 them, we don't want to actually continue the inferior -- we just
326 want to report the stop. In this case, we just pretend to
327 continue. See the comment by the definition of "pending_stops"
328 for details on why this is needed. */
329 for (const auto &item
: pending_stops
)
331 if (desired_stop_thread_id
== -1
332 || desired_stop_thread_id
== item
.thread_id
)
334 DEBUG_EVENTS (("windows_continue - pending stop anticipated, "
335 "desired=0x%x, item=0x%x\n",
336 desired_stop_thread_id
, item
.thread_id
));
344 /* See nat/windows-nat.h. */
346 gdb::optional
<pending_stop
>
347 fetch_pending_stop (bool debug_events
)
349 gdb::optional
<pending_stop
> result
;
350 for (auto iter
= pending_stops
.begin ();
351 iter
!= pending_stops
.end ();
354 if (desired_stop_thread_id
== -1
355 || desired_stop_thread_id
== iter
->thread_id
)
358 current_event
= iter
->event
;
360 DEBUG_EVENTS (("get_windows_debug_event - "
361 "pending stop found in 0x%x (desired=0x%x)\n",
362 iter
->thread_id
, desired_stop_thread_id
));
364 pending_stops
.erase (iter
);
372 /* See nat/windows-nat.h. */
375 continue_last_debug_event (DWORD continue_status
, bool debug_events
)
377 DEBUG_EVENTS (("ContinueDebugEvent (cpid=%d, ctid=0x%x, %s);\n",
378 (unsigned) last_wait_event
.dwProcessId
,
379 (unsigned) last_wait_event
.dwThreadId
,
380 continue_status
== DBG_CONTINUE
?
381 "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED"));
383 return ContinueDebugEvent (last_wait_event
.dwProcessId
,
384 last_wait_event
.dwThreadId
,
388 /* See nat/windows-nat.h. */
391 wait_for_debug_event (DEBUG_EVENT
*event
, DWORD timeout
)
393 BOOL result
= WaitForDebugEvent (event
, timeout
);
395 last_wait_event
= *event
;