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 windows_thread_info::~windows_thread_info ()
46 windows_thread_info::suspend ()
51 if (SuspendThread (h
) == (DWORD
) -1)
53 DWORD err
= GetLastError ();
55 /* We get Access Denied (5) when trying to suspend
56 threads that Windows started on behalf of the
57 debuggee, usually when those threads are just
59 We can get Invalid Handle (6) if the main thread
61 if (err
!= ERROR_INVALID_HANDLE
&& err
!= ERROR_ACCESS_DENIED
)
62 warning (_("SuspendThread (tid=0x%x) failed. (winerr %u)"),
63 (unsigned) tid
, (unsigned) err
);
71 windows_thread_info::resume ()
75 stopped_at_software_breakpoint
= false;
77 if (ResumeThread (h
) == (DWORD
) -1)
79 DWORD err
= GetLastError ();
80 warning (_("warning: ResumeThread (tid=0x%x) failed. (winerr %u)"),
81 (unsigned) tid
, (unsigned) err
);
88 get_image_name (HANDLE h
, void *address
, int unicode
)
91 static char buf
[MAX_PATH
];
93 static char buf
[(2 * MAX_PATH
) + 1];
95 DWORD size
= unicode
? sizeof (WCHAR
) : sizeof (char);
101 /* Attempt to read the name of the dll that was detected.
102 This is documented to work only when actively debugging
103 a program. It will not work for attached processes. */
108 /* Windows CE reports the address of the image name,
109 instead of an address of a pointer into the image name. */
110 address_ptr
= address
;
112 /* See if we could read the address of a string, and that the
113 address isn't null. */
114 if (!ReadProcessMemory (h
, address
, &address_ptr
,
115 sizeof (address_ptr
), &done
)
116 || done
!= sizeof (address_ptr
)
121 /* Find the length of the string. */
122 while (ReadProcessMemory (h
, address_ptr
+ len
++ * size
, &b
, size
, &done
)
123 && (b
[0] != 0 || b
[size
- 1] != 0) && done
== size
)
127 ReadProcessMemory (h
, address_ptr
, buf
, len
, &done
);
130 WCHAR
*unicode_address
= (WCHAR
*) alloca (len
* sizeof (WCHAR
));
131 ReadProcessMemory (h
, address_ptr
, unicode_address
, len
* sizeof (WCHAR
),
134 wcstombs (buf
, unicode_address
, MAX_PATH
);
136 WideCharToMultiByte (CP_ACP
, 0, unicode_address
, len
, buf
, sizeof buf
,
144 /* The exception thrown by a program to tell the debugger the name of
145 a thread. The exception record contains an ID of a thread and a
146 name to give it. This exception has no documented name, but MSDN
147 dubs it "MS_VC_EXCEPTION" in one code example. */
148 #define MS_VC_EXCEPTION 0x406d1388
150 handle_exception_result
151 handle_exception (struct target_waitstatus
*ourstatus
, bool debug_exceptions
)
153 #define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \
154 debug_printf ("gdb: Target exception %s at %s\n", x, \
155 host_address_to_string (\
156 current_event.u.Exception.ExceptionRecord.ExceptionAddress))
158 EXCEPTION_RECORD
*rec
= ¤t_event
.u
.Exception
.ExceptionRecord
;
159 DWORD code
= rec
->ExceptionCode
;
160 handle_exception_result result
= HANDLE_EXCEPTION_HANDLED
;
162 memcpy (&siginfo_er
, rec
, sizeof siginfo_er
);
164 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
166 /* Record the context of the current thread. */
167 thread_rec (ptid_t (current_event
.dwProcessId
, current_event
.dwThreadId
, 0),
172 case EXCEPTION_ACCESS_VIOLATION
:
173 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
174 ourstatus
->value
.sig
= GDB_SIGNAL_SEGV
;
177 /* See if the access violation happened within the cygwin DLL
178 itself. Cygwin uses a kind of exception handling to deal
179 with passed-in invalid addresses. gdb should not treat
180 these as real SEGVs since they will be silently handled by
181 cygwin. A real SEGV will (theoretically) be caught by
182 cygwin later in the process and will be sent as a
183 cygwin-specific-signal. So, ignore SEGVs if they show up
184 within the text segment of the DLL itself. */
186 CORE_ADDR addr
= (CORE_ADDR
) (uintptr_t) rec
->ExceptionAddress
;
188 if ((!cygwin_exceptions
&& (addr
>= cygwin_load_start
189 && addr
< cygwin_load_end
))
190 || (find_pc_partial_function (addr
, &fn
, NULL
, NULL
)
191 && startswith (fn
, "KERNEL32!IsBad")))
192 return HANDLE_EXCEPTION_UNHANDLED
;
196 case STATUS_STACK_OVERFLOW
:
197 DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
198 ourstatus
->value
.sig
= GDB_SIGNAL_SEGV
;
200 case STATUS_FLOAT_DENORMAL_OPERAND
:
201 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
202 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
204 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
205 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
206 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
208 case STATUS_FLOAT_INEXACT_RESULT
:
209 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
210 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
212 case STATUS_FLOAT_INVALID_OPERATION
:
213 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
214 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
216 case STATUS_FLOAT_OVERFLOW
:
217 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
218 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
220 case STATUS_FLOAT_STACK_CHECK
:
221 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
222 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
224 case STATUS_FLOAT_UNDERFLOW
:
225 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
226 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
228 case STATUS_FLOAT_DIVIDE_BY_ZERO
:
229 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
230 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
232 case STATUS_INTEGER_DIVIDE_BY_ZERO
:
233 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
234 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
236 case STATUS_INTEGER_OVERFLOW
:
237 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
238 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
240 case EXCEPTION_BREAKPOINT
:
242 if (ignore_first_breakpoint
)
244 /* For WOW64 processes, there are always 2 breakpoint exceptions
245 on startup, first a BREAKPOINT for the 64bit ntdll.dll,
246 then a WX86_BREAKPOINT for the 32bit ntdll.dll.
247 Here we only care about the WX86_BREAKPOINT's. */
248 ourstatus
->kind
= TARGET_WAITKIND_SPURIOUS
;
249 ignore_first_breakpoint
= false;
253 case STATUS_WX86_BREAKPOINT
:
254 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
255 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
257 /* Remove the initial breakpoint. */
258 check_breakpoints ((CORE_ADDR
) (long) current_event
259 .u
.Exception
.ExceptionRecord
.ExceptionAddress
);
263 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
264 ourstatus
->value
.sig
= GDB_SIGNAL_INT
;
266 case DBG_CONTROL_BREAK
:
267 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
268 ourstatus
->value
.sig
= GDB_SIGNAL_INT
;
270 case EXCEPTION_SINGLE_STEP
:
271 case STATUS_WX86_SINGLE_STEP
:
272 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
273 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
275 case EXCEPTION_ILLEGAL_INSTRUCTION
:
276 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
277 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
279 case EXCEPTION_PRIV_INSTRUCTION
:
280 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
281 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
283 case EXCEPTION_NONCONTINUABLE_EXCEPTION
:
284 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
285 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
287 case MS_VC_EXCEPTION
:
288 DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION");
289 if (handle_ms_vc_exception (rec
))
291 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
292 result
= HANDLE_EXCEPTION_IGNORED
;
295 /* treat improperly formed exception as unknown */
298 /* Treat unhandled first chance exceptions specially. */
299 if (current_event
.u
.Exception
.dwFirstChance
)
300 return HANDLE_EXCEPTION_UNHANDLED
;
301 debug_printf ("gdb: unknown target exception 0x%08x at %s\n",
302 (unsigned) current_event
.u
.Exception
.ExceptionRecord
.ExceptionCode
,
303 host_address_to_string (
304 current_event
.u
.Exception
.ExceptionRecord
.ExceptionAddress
));
305 ourstatus
->value
.sig
= GDB_SIGNAL_UNKNOWN
;
309 last_sig
= ourstatus
->value
.sig
;
312 #undef DEBUG_EXCEPTION_SIMPLE