bfd: add elfcore_write_file_note
[deliverable/binutils-gdb.git] / gdb / nat / windows-nat.c
CommitLineData
98a03287 1/* Internal interfaces for the Windows code
3666a048 2 Copyright (C) 1995-2021 Free Software Foundation, Inc.
98a03287
TT
3
4 This file is part of GDB.
5
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.
10
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.
15
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/>. */
18
19#include "gdbsupport/common-defs.h"
20#include "nat/windows-nat.h"
8d30e395
TT
21#include "gdbsupport/common-debug.h"
22
4834dad0
TT
23namespace windows_nat
24{
25
3c76026d
TT
26HANDLE current_process_handle;
27DWORD current_process_id;
28DWORD main_thread_id;
29enum gdb_signal last_sig = GDB_SIGNAL_0;
30DEBUG_EVENT current_event;
71fbdbaf
TT
31
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. */
37static DEBUG_EVENT last_wait_event;
38
3c76026d
TT
39DWORD desired_stop_thread_id = -1;
40std::vector<pending_stop> pending_stops;
41EXCEPTION_RECORD siginfo_er;
42
13302e95 43#ifdef __x86_64__
99bb393f 44bool wow64_process = false;
13302e95
HD
45bool ignore_first_breakpoint = false;
46#endif
47
e758e19c
TT
48/* Note that 'debug_events' must be locally defined in the relevant
49 functions. */
50#define DEBUG_EVENTS(x) if (debug_events) debug_printf x
51
65bafd5b
TT
52windows_thread_info::~windows_thread_info ()
53{
65bafd5b
TT
54}
55
98a03287
TT
56void
57windows_thread_info::suspend ()
58{
59 if (suspended != 0)
60 return;
61
62 if (SuspendThread (h) == (DWORD) -1)
63 {
64 DWORD err = GetLastError ();
65
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
69 about to exit.
70 We can get Invalid Handle (6) if the main thread
71 has exited. */
72 if (err != ERROR_INVALID_HANDLE && err != ERROR_ACCESS_DENIED)
73 warning (_("SuspendThread (tid=0x%x) failed. (winerr %u)"),
74 (unsigned) tid, (unsigned) err);
75 suspended = -1;
76 }
77 else
78 suspended = 1;
79}
80
81void
82windows_thread_info::resume ()
83{
84 if (suspended > 0)
85 {
0a4afda3
TT
86 stopped_at_software_breakpoint = false;
87
98a03287
TT
88 if (ResumeThread (h) == (DWORD) -1)
89 {
90 DWORD err = GetLastError ();
91 warning (_("warning: ResumeThread (tid=0x%x) failed. (winerr %u)"),
92 (unsigned) tid, (unsigned) err);
93 }
94 }
95 suspended = 0;
96}
4834dad0 97
9d8679cc
TT
98const char *
99get_image_name (HANDLE h, void *address, int unicode)
100{
101#ifdef __CYGWIN__
102 static char buf[MAX_PATH];
103#else
104 static char buf[(2 * MAX_PATH) + 1];
105#endif
106 DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
107 char *address_ptr;
108 int len = 0;
109 char b[2];
110 SIZE_T done;
111
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. */
115 if (address == NULL)
116 return NULL;
117
118#ifdef _WIN32_WCE
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;
122#else
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)
128 || !address_ptr)
129 return NULL;
130#endif
131
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)
135 continue;
136
137 if (!unicode)
138 ReadProcessMemory (h, address_ptr, buf, len, &done);
139 else
140 {
141 WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR));
142 ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
143 &done);
144#ifdef __CYGWIN__
145 wcstombs (buf, unicode_address, MAX_PATH);
146#else
147 WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, sizeof buf,
148 0, 0);
149#endif
150 }
151
152 return buf;
153}
154
8d30e395
TT
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
160
161handle_exception_result
162handle_exception (struct target_waitstatus *ourstatus, bool debug_exceptions)
163{
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))
168
169 EXCEPTION_RECORD *rec = &current_event.u.Exception.ExceptionRecord;
170 DWORD code = rec->ExceptionCode;
171 handle_exception_result result = HANDLE_EXCEPTION_HANDLED;
172
173 memcpy (&siginfo_er, rec, sizeof siginfo_er);
174
175 ourstatus->kind = TARGET_WAITKIND_STOPPED;
176
177 /* Record the context of the current thread. */
178 thread_rec (ptid_t (current_event.dwProcessId, current_event.dwThreadId, 0),
179 DONT_SUSPEND);
180
181 switch (code)
182 {
183 case EXCEPTION_ACCESS_VIOLATION:
184 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
185 ourstatus->value.sig = GDB_SIGNAL_SEGV;
a010605f
TT
186 if (handle_access_violation (rec))
187 return HANDLE_EXCEPTION_UNHANDLED;
8d30e395
TT
188 break;
189 case STATUS_STACK_OVERFLOW:
190 DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
191 ourstatus->value.sig = GDB_SIGNAL_SEGV;
192 break;
193 case STATUS_FLOAT_DENORMAL_OPERAND:
194 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
195 ourstatus->value.sig = GDB_SIGNAL_FPE;
196 break;
197 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
198 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
199 ourstatus->value.sig = GDB_SIGNAL_FPE;
200 break;
201 case STATUS_FLOAT_INEXACT_RESULT:
202 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
203 ourstatus->value.sig = GDB_SIGNAL_FPE;
204 break;
205 case STATUS_FLOAT_INVALID_OPERATION:
206 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
207 ourstatus->value.sig = GDB_SIGNAL_FPE;
208 break;
209 case STATUS_FLOAT_OVERFLOW:
210 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
211 ourstatus->value.sig = GDB_SIGNAL_FPE;
212 break;
213 case STATUS_FLOAT_STACK_CHECK:
214 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
215 ourstatus->value.sig = GDB_SIGNAL_FPE;
216 break;
217 case STATUS_FLOAT_UNDERFLOW:
218 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
219 ourstatus->value.sig = GDB_SIGNAL_FPE;
220 break;
221 case STATUS_FLOAT_DIVIDE_BY_ZERO:
222 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
223 ourstatus->value.sig = GDB_SIGNAL_FPE;
224 break;
225 case STATUS_INTEGER_DIVIDE_BY_ZERO:
226 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
227 ourstatus->value.sig = GDB_SIGNAL_FPE;
228 break;
229 case STATUS_INTEGER_OVERFLOW:
230 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
231 ourstatus->value.sig = GDB_SIGNAL_FPE;
232 break;
233 case EXCEPTION_BREAKPOINT:
234#ifdef __x86_64__
235 if (ignore_first_breakpoint)
236 {
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;
243 }
99bb393f
HD
244 else if (wow64_process)
245 {
246 /* This breakpoint exception is triggered for WOW64 processes when
247 reaching an int3 instruction in 64bit code.
248 gdb checks for int3 in case of SIGTRAP, this fails because
249 Wow64GetThreadContext can only report the pc of 32bit code, and
250 gdb lets the target process continue.
251 So handle it as SIGINT instead, then the target is stopped
252 unconditionally. */
253 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
254 rec->ExceptionCode = DBG_CONTROL_C;
255 ourstatus->value.sig = GDB_SIGNAL_INT;
256 break;
257 }
8d30e395
TT
258#endif
259 /* FALLTHROUGH */
260 case STATUS_WX86_BREAKPOINT:
261 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
262 ourstatus->value.sig = GDB_SIGNAL_TRAP;
263#ifdef _WIN32_WCE
264 /* Remove the initial breakpoint. */
265 check_breakpoints ((CORE_ADDR) (long) current_event
266 .u.Exception.ExceptionRecord.ExceptionAddress);
267#endif
268 break;
269 case DBG_CONTROL_C:
270 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
271 ourstatus->value.sig = GDB_SIGNAL_INT;
272 break;
273 case DBG_CONTROL_BREAK:
274 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
275 ourstatus->value.sig = GDB_SIGNAL_INT;
276 break;
277 case EXCEPTION_SINGLE_STEP:
278 case STATUS_WX86_SINGLE_STEP:
279 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
280 ourstatus->value.sig = GDB_SIGNAL_TRAP;
281 break;
282 case EXCEPTION_ILLEGAL_INSTRUCTION:
283 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
284 ourstatus->value.sig = GDB_SIGNAL_ILL;
285 break;
286 case EXCEPTION_PRIV_INSTRUCTION:
287 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
288 ourstatus->value.sig = GDB_SIGNAL_ILL;
289 break;
290 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
291 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
292 ourstatus->value.sig = GDB_SIGNAL_ILL;
293 break;
294 case MS_VC_EXCEPTION:
295 DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION");
296 if (handle_ms_vc_exception (rec))
297 {
298 ourstatus->value.sig = GDB_SIGNAL_TRAP;
299 result = HANDLE_EXCEPTION_IGNORED;
300 break;
301 }
302 /* treat improperly formed exception as unknown */
303 /* FALLTHROUGH */
304 default:
305 /* Treat unhandled first chance exceptions specially. */
306 if (current_event.u.Exception.dwFirstChance)
307 return HANDLE_EXCEPTION_UNHANDLED;
308 debug_printf ("gdb: unknown target exception 0x%08x at %s\n",
309 (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionCode,
310 host_address_to_string (
311 current_event.u.Exception.ExceptionRecord.ExceptionAddress));
312 ourstatus->value.sig = GDB_SIGNAL_UNKNOWN;
313 break;
314 }
315
316 last_sig = ourstatus->value.sig;
317 return result;
318
319#undef DEBUG_EXCEPTION_SIMPLE
320}
321
e758e19c
TT
322/* See nat/windows-nat.h. */
323
324bool
325matching_pending_stop (bool debug_events)
326{
327 /* If there are pending stops, and we might plausibly hit one of
328 them, we don't want to actually continue the inferior -- we just
329 want to report the stop. In this case, we just pretend to
330 continue. See the comment by the definition of "pending_stops"
331 for details on why this is needed. */
332 for (const auto &item : pending_stops)
333 {
334 if (desired_stop_thread_id == -1
335 || desired_stop_thread_id == item.thread_id)
336 {
337 DEBUG_EVENTS (("windows_continue - pending stop anticipated, "
338 "desired=0x%x, item=0x%x\n",
339 desired_stop_thread_id, item.thread_id));
340 return true;
341 }
342 }
343
344 return false;
345}
346
347/* See nat/windows-nat.h. */
348
d2977bc4
TT
349gdb::optional<pending_stop>
350fetch_pending_stop (bool debug_events)
351{
352 gdb::optional<pending_stop> result;
353 for (auto iter = pending_stops.begin ();
354 iter != pending_stops.end ();
355 ++iter)
356 {
357 if (desired_stop_thread_id == -1
358 || desired_stop_thread_id == iter->thread_id)
359 {
360 result = *iter;
361 current_event = iter->event;
362
363 DEBUG_EVENTS (("get_windows_debug_event - "
364 "pending stop found in 0x%x (desired=0x%x)\n",
365 iter->thread_id, desired_stop_thread_id));
366
367 pending_stops.erase (iter);
368 break;
369 }
370 }
371
372 return result;
373}
374
375/* See nat/windows-nat.h. */
376
e758e19c
TT
377BOOL
378continue_last_debug_event (DWORD continue_status, bool debug_events)
379{
380 DEBUG_EVENTS (("ContinueDebugEvent (cpid=%d, ctid=0x%x, %s);\n",
381 (unsigned) last_wait_event.dwProcessId,
382 (unsigned) last_wait_event.dwThreadId,
383 continue_status == DBG_CONTINUE ?
384 "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED"));
385
386 return ContinueDebugEvent (last_wait_event.dwProcessId,
387 last_wait_event.dwThreadId,
388 continue_status);
389}
390
2c1d95e8
TT
391/* See nat/windows-nat.h. */
392
393BOOL
394wait_for_debug_event (DEBUG_EVENT *event, DWORD timeout)
395{
396 BOOL result = WaitForDebugEvent (event, timeout);
397 if (result)
398 last_wait_event = *event;
399 return result;
400}
e758e19c 401
4834dad0 402}
This page took 0.236076 seconds and 4 git commands to generate.