]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/nat/windows-nat.c
gdb, gdbserver: make target_waitstatus safe
[thirdparty/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
9e439f00
TT
48AdjustTokenPrivileges_ftype *AdjustTokenPrivileges;
49DebugActiveProcessStop_ftype *DebugActiveProcessStop;
50DebugBreakProcess_ftype *DebugBreakProcess;
51DebugSetProcessKillOnExit_ftype *DebugSetProcessKillOnExit;
52EnumProcessModules_ftype *EnumProcessModules;
53#ifdef __x86_64__
54EnumProcessModulesEx_ftype *EnumProcessModulesEx;
55#endif
56GetModuleInformation_ftype *GetModuleInformation;
57GetModuleFileNameExA_ftype *GetModuleFileNameExA;
58GetModuleFileNameExW_ftype *GetModuleFileNameExW;
59LookupPrivilegeValueA_ftype *LookupPrivilegeValueA;
60OpenProcessToken_ftype *OpenProcessToken;
61GetCurrentConsoleFont_ftype *GetCurrentConsoleFont;
62GetConsoleFontSize_ftype *GetConsoleFontSize;
63#ifdef __x86_64__
64Wow64SuspendThread_ftype *Wow64SuspendThread;
65Wow64GetThreadContext_ftype *Wow64GetThreadContext;
66Wow64SetThreadContext_ftype *Wow64SetThreadContext;
67Wow64GetThreadSelectorEntry_ftype *Wow64GetThreadSelectorEntry;
68#endif
de071872 69GenerateConsoleCtrlEvent_ftype *GenerateConsoleCtrlEvent;
9e439f00 70
e758e19c
TT
71/* Note that 'debug_events' must be locally defined in the relevant
72 functions. */
4ef367bf
TT
73#define DEBUG_EVENTS(fmt, ...) \
74 debug_prefixed_printf_cond (debug_events, "windows events", fmt, \
75 ## __VA_ARGS__)
e758e19c 76
65bafd5b
TT
77windows_thread_info::~windows_thread_info ()
78{
65bafd5b
TT
79}
80
98a03287
TT
81void
82windows_thread_info::suspend ()
83{
84 if (suspended != 0)
85 return;
86
87 if (SuspendThread (h) == (DWORD) -1)
88 {
89 DWORD err = GetLastError ();
90
91 /* We get Access Denied (5) when trying to suspend
92 threads that Windows started on behalf of the
93 debuggee, usually when those threads are just
94 about to exit.
95 We can get Invalid Handle (6) if the main thread
96 has exited. */
97 if (err != ERROR_INVALID_HANDLE && err != ERROR_ACCESS_DENIED)
98 warning (_("SuspendThread (tid=0x%x) failed. (winerr %u)"),
99 (unsigned) tid, (unsigned) err);
100 suspended = -1;
101 }
102 else
103 suspended = 1;
104}
105
106void
107windows_thread_info::resume ()
108{
109 if (suspended > 0)
110 {
0a4afda3
TT
111 stopped_at_software_breakpoint = false;
112
98a03287
TT
113 if (ResumeThread (h) == (DWORD) -1)
114 {
115 DWORD err = GetLastError ();
116 warning (_("warning: ResumeThread (tid=0x%x) failed. (winerr %u)"),
117 (unsigned) tid, (unsigned) err);
118 }
119 }
120 suspended = 0;
121}
4834dad0 122
1bee48c7
TT
123/* Return the name of the DLL referenced by H at ADDRESS. UNICODE
124 determines what sort of string is read from the inferior. Returns
125 the name of the DLL, or NULL on error. If a name is returned, it
126 is stored in a static buffer which is valid until the next call to
127 get_image_name. */
128
129static const char *
9d8679cc
TT
130get_image_name (HANDLE h, void *address, int unicode)
131{
132#ifdef __CYGWIN__
133 static char buf[MAX_PATH];
134#else
135 static char buf[(2 * MAX_PATH) + 1];
136#endif
137 DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
138 char *address_ptr;
139 int len = 0;
140 char b[2];
141 SIZE_T done;
142
143 /* Attempt to read the name of the dll that was detected.
144 This is documented to work only when actively debugging
145 a program. It will not work for attached processes. */
146 if (address == NULL)
147 return NULL;
148
9d8679cc
TT
149 /* See if we could read the address of a string, and that the
150 address isn't null. */
151 if (!ReadProcessMemory (h, address, &address_ptr,
152 sizeof (address_ptr), &done)
153 || done != sizeof (address_ptr)
154 || !address_ptr)
155 return NULL;
9d8679cc
TT
156
157 /* Find the length of the string. */
158 while (ReadProcessMemory (h, address_ptr + len++ * size, &b, size, &done)
159 && (b[0] != 0 || b[size - 1] != 0) && done == size)
160 continue;
161
162 if (!unicode)
163 ReadProcessMemory (h, address_ptr, buf, len, &done);
164 else
165 {
166 WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR));
167 ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
168 &done);
169#ifdef __CYGWIN__
170 wcstombs (buf, unicode_address, MAX_PATH);
171#else
172 WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, sizeof buf,
173 0, 0);
174#endif
175 }
176
177 return buf;
178}
179
8d30e395
TT
180/* The exception thrown by a program to tell the debugger the name of
181 a thread. The exception record contains an ID of a thread and a
182 name to give it. This exception has no documented name, but MSDN
183 dubs it "MS_VC_EXCEPTION" in one code example. */
184#define MS_VC_EXCEPTION 0x406d1388
185
186handle_exception_result
187handle_exception (struct target_waitstatus *ourstatus, bool debug_exceptions)
188{
189#define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \
190 debug_printf ("gdb: Target exception %s at %s\n", x, \
191 host_address_to_string (\
192 current_event.u.Exception.ExceptionRecord.ExceptionAddress))
193
194 EXCEPTION_RECORD *rec = &current_event.u.Exception.ExceptionRecord;
195 DWORD code = rec->ExceptionCode;
196 handle_exception_result result = HANDLE_EXCEPTION_HANDLED;
197
198 memcpy (&siginfo_er, rec, sizeof siginfo_er);
199
8d30e395
TT
200 /* Record the context of the current thread. */
201 thread_rec (ptid_t (current_event.dwProcessId, current_event.dwThreadId, 0),
202 DONT_SUSPEND);
203
204 switch (code)
205 {
206 case EXCEPTION_ACCESS_VIOLATION:
207 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
183be222 208 ourstatus->set_stopped (GDB_SIGNAL_SEGV);
a010605f
TT
209 if (handle_access_violation (rec))
210 return HANDLE_EXCEPTION_UNHANDLED;
8d30e395
TT
211 break;
212 case STATUS_STACK_OVERFLOW:
213 DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
183be222 214 ourstatus->set_stopped (GDB_SIGNAL_SEGV);
8d30e395
TT
215 break;
216 case STATUS_FLOAT_DENORMAL_OPERAND:
217 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
183be222 218 ourstatus->set_stopped (GDB_SIGNAL_FPE);
8d30e395
TT
219 break;
220 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
221 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
183be222 222 ourstatus->set_stopped (GDB_SIGNAL_FPE);
8d30e395
TT
223 break;
224 case STATUS_FLOAT_INEXACT_RESULT:
225 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
183be222 226 ourstatus->set_stopped (GDB_SIGNAL_FPE);
8d30e395
TT
227 break;
228 case STATUS_FLOAT_INVALID_OPERATION:
229 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
183be222 230 ourstatus->set_stopped (GDB_SIGNAL_FPE);
8d30e395
TT
231 break;
232 case STATUS_FLOAT_OVERFLOW:
233 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
183be222 234 ourstatus->set_stopped (GDB_SIGNAL_FPE);
8d30e395
TT
235 break;
236 case STATUS_FLOAT_STACK_CHECK:
237 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
183be222 238 ourstatus->set_stopped (GDB_SIGNAL_FPE);
8d30e395
TT
239 break;
240 case STATUS_FLOAT_UNDERFLOW:
241 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
183be222 242 ourstatus->set_stopped (GDB_SIGNAL_FPE);
8d30e395
TT
243 break;
244 case STATUS_FLOAT_DIVIDE_BY_ZERO:
245 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
183be222 246 ourstatus->set_stopped (GDB_SIGNAL_FPE);
8d30e395
TT
247 break;
248 case STATUS_INTEGER_DIVIDE_BY_ZERO:
249 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
183be222 250 ourstatus->set_stopped (GDB_SIGNAL_FPE);
8d30e395
TT
251 break;
252 case STATUS_INTEGER_OVERFLOW:
253 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
183be222 254 ourstatus->set_stopped (GDB_SIGNAL_FPE);
8d30e395
TT
255 break;
256 case EXCEPTION_BREAKPOINT:
257#ifdef __x86_64__
258 if (ignore_first_breakpoint)
259 {
260 /* For WOW64 processes, there are always 2 breakpoint exceptions
261 on startup, first a BREAKPOINT for the 64bit ntdll.dll,
262 then a WX86_BREAKPOINT for the 32bit ntdll.dll.
263 Here we only care about the WX86_BREAKPOINT's. */
183be222 264 ourstatus->set_spurious ();
8d30e395
TT
265 ignore_first_breakpoint = false;
266 }
99bb393f
HD
267 else if (wow64_process)
268 {
269 /* This breakpoint exception is triggered for WOW64 processes when
270 reaching an int3 instruction in 64bit code.
271 gdb checks for int3 in case of SIGTRAP, this fails because
272 Wow64GetThreadContext can only report the pc of 32bit code, and
273 gdb lets the target process continue.
274 So handle it as SIGINT instead, then the target is stopped
275 unconditionally. */
276 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
277 rec->ExceptionCode = DBG_CONTROL_C;
183be222 278 ourstatus->set_stopped (GDB_SIGNAL_INT);
99bb393f
HD
279 break;
280 }
8d30e395
TT
281#endif
282 /* FALLTHROUGH */
283 case STATUS_WX86_BREAKPOINT:
284 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
183be222 285 ourstatus->set_stopped (GDB_SIGNAL_TRAP);
8d30e395
TT
286 break;
287 case DBG_CONTROL_C:
288 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
183be222 289 ourstatus->set_stopped (GDB_SIGNAL_INT);
8d30e395
TT
290 break;
291 case DBG_CONTROL_BREAK:
292 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
183be222 293 ourstatus->set_stopped (GDB_SIGNAL_INT);
8d30e395
TT
294 break;
295 case EXCEPTION_SINGLE_STEP:
296 case STATUS_WX86_SINGLE_STEP:
297 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
183be222 298 ourstatus->set_stopped (GDB_SIGNAL_TRAP);
8d30e395
TT
299 break;
300 case EXCEPTION_ILLEGAL_INSTRUCTION:
301 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
183be222 302 ourstatus->set_stopped (GDB_SIGNAL_ILL);
8d30e395
TT
303 break;
304 case EXCEPTION_PRIV_INSTRUCTION:
305 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
183be222 306 ourstatus->set_stopped (GDB_SIGNAL_ILL);
8d30e395
TT
307 break;
308 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
309 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
183be222 310 ourstatus->set_stopped (GDB_SIGNAL_ILL);
8d30e395
TT
311 break;
312 case MS_VC_EXCEPTION:
313 DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION");
314 if (handle_ms_vc_exception (rec))
315 {
183be222 316 ourstatus->set_stopped (GDB_SIGNAL_TRAP);
8d30e395
TT
317 result = HANDLE_EXCEPTION_IGNORED;
318 break;
319 }
320 /* treat improperly formed exception as unknown */
321 /* FALLTHROUGH */
322 default:
323 /* Treat unhandled first chance exceptions specially. */
324 if (current_event.u.Exception.dwFirstChance)
325 return HANDLE_EXCEPTION_UNHANDLED;
326 debug_printf ("gdb: unknown target exception 0x%08x at %s\n",
327 (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionCode,
328 host_address_to_string (
329 current_event.u.Exception.ExceptionRecord.ExceptionAddress));
183be222 330 ourstatus->set_stopped (GDB_SIGNAL_UNKNOWN);
8d30e395
TT
331 break;
332 }
333
183be222
SM
334 if (ourstatus->kind () == TARGET_WAITKIND_STOPPED)
335 last_sig = ourstatus->sig ();
336
8d30e395
TT
337 return result;
338
339#undef DEBUG_EXCEPTION_SIMPLE
340}
341
e228ef97
TT
342/* Iterate over all DLLs currently mapped by our inferior, looking for
343 a DLL which is loaded at LOAD_ADDR. If found, add the DLL to our
344 list of solibs; otherwise do nothing. LOAD_ADDR NULL means add all
345 DLLs to the list of solibs; this is used when the inferior finishes
346 its initialization, and all the DLLs it statically depends on are
347 presumed loaded. */
348
349static void
350windows_add_dll (LPVOID load_addr)
351{
352 HMODULE dummy_hmodule;
353 DWORD cb_needed;
354 HMODULE *hmodules;
355 int i;
356
357#ifdef __x86_64__
358 if (wow64_process)
359 {
360 if (EnumProcessModulesEx (current_process_handle, &dummy_hmodule,
361 sizeof (HMODULE), &cb_needed,
362 LIST_MODULES_32BIT) == 0)
363 return;
364 }
365 else
366#endif
367 {
368 if (EnumProcessModules (current_process_handle, &dummy_hmodule,
369 sizeof (HMODULE), &cb_needed) == 0)
370 return;
371 }
372
373 if (cb_needed < 1)
374 return;
375
376 hmodules = (HMODULE *) alloca (cb_needed);
377#ifdef __x86_64__
378 if (wow64_process)
379 {
380 if (EnumProcessModulesEx (current_process_handle, hmodules,
381 cb_needed, &cb_needed,
382 LIST_MODULES_32BIT) == 0)
383 return;
384 }
385 else
386#endif
387 {
388 if (EnumProcessModules (current_process_handle, hmodules,
389 cb_needed, &cb_needed) == 0)
390 return;
391 }
392
393 char system_dir[MAX_PATH];
394 char syswow_dir[MAX_PATH];
395 size_t system_dir_len = 0;
396 bool convert_syswow_dir = false;
397#ifdef __x86_64__
398 if (wow64_process)
399#endif
400 {
401 /* This fails on 32bit Windows because it has no SysWOW64 directory,
402 and in this case a path conversion isn't necessary. */
403 UINT len = GetSystemWow64DirectoryA (syswow_dir, sizeof (syswow_dir));
404 if (len > 0)
405 {
406 /* Check that we have passed a large enough buffer. */
407 gdb_assert (len < sizeof (syswow_dir));
408
409 len = GetSystemDirectoryA (system_dir, sizeof (system_dir));
410 /* Error check. */
411 gdb_assert (len != 0);
412 /* Check that we have passed a large enough buffer. */
413 gdb_assert (len < sizeof (system_dir));
414
415 strcat (system_dir, "\\");
416 strcat (syswow_dir, "\\");
417 system_dir_len = strlen (system_dir);
418
419 convert_syswow_dir = true;
420 }
421
422 }
423 for (i = 1; i < (int) (cb_needed / sizeof (HMODULE)); i++)
424 {
425 MODULEINFO mi;
426#ifdef __USEWIDE
427 wchar_t dll_name[MAX_PATH];
428 char dll_name_mb[MAX_PATH];
429#else
430 char dll_name[MAX_PATH];
431#endif
432 const char *name;
433 if (GetModuleInformation (current_process_handle, hmodules[i],
434 &mi, sizeof (mi)) == 0)
435 continue;
436
437 if (GetModuleFileNameEx (current_process_handle, hmodules[i],
438 dll_name, sizeof (dll_name)) == 0)
439 continue;
440#ifdef __USEWIDE
441 wcstombs (dll_name_mb, dll_name, MAX_PATH);
442 name = dll_name_mb;
443#else
444 name = dll_name;
445#endif
446 /* Convert the DLL path of 32bit processes returned by
447 GetModuleFileNameEx from the 64bit system directory to the
448 32bit syswow64 directory if necessary. */
449 std::string syswow_dll_path;
450 if (convert_syswow_dir
451 && strncasecmp (name, system_dir, system_dir_len) == 0
452 && strchr (name + system_dir_len, '\\') == nullptr)
453 {
454 syswow_dll_path = syswow_dir;
455 syswow_dll_path += name + system_dir_len;
456 name = syswow_dll_path.c_str();
457 }
458
459 /* Record the DLL if either LOAD_ADDR is NULL or the address
460 at which the DLL was loaded is equal to LOAD_ADDR. */
461 if (!(load_addr != nullptr && mi.lpBaseOfDll != load_addr))
462 {
463 handle_load_dll (name, mi.lpBaseOfDll);
464 if (load_addr != nullptr)
465 return;
466 }
467 }
468}
469
470/* See nat/windows-nat.h. */
471
472void
473dll_loaded_event ()
474{
475 gdb_assert (current_event.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT);
476
477 LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
478 const char *dll_name;
479
480 /* Try getting the DLL name via the lpImageName field of the event.
481 Note that Microsoft documents this fields as strictly optional,
482 in the sense that it might be NULL. And the first DLL event in
483 particular is explicitly documented as "likely not pass[ed]"
484 (source: MSDN LOAD_DLL_DEBUG_INFO structure). */
485 dll_name = get_image_name (current_process_handle,
486 event->lpImageName, event->fUnicode);
487 /* If the DLL name could not be gleaned via lpImageName, try harder
488 by enumerating all the DLLs loaded into the inferior, looking for
489 one that is loaded at base address = lpBaseOfDll. */
490 if (dll_name != nullptr)
491 handle_load_dll (dll_name, event->lpBaseOfDll);
492 else if (event->lpBaseOfDll != nullptr)
493 windows_add_dll (event->lpBaseOfDll);
494}
495
496/* See nat/windows-nat.h. */
497
498void
499windows_add_all_dlls ()
500{
501 windows_add_dll (nullptr);
502}
503
e758e19c
TT
504/* See nat/windows-nat.h. */
505
506bool
507matching_pending_stop (bool debug_events)
508{
509 /* If there are pending stops, and we might plausibly hit one of
510 them, we don't want to actually continue the inferior -- we just
511 want to report the stop. In this case, we just pretend to
512 continue. See the comment by the definition of "pending_stops"
513 for details on why this is needed. */
514 for (const auto &item : pending_stops)
515 {
516 if (desired_stop_thread_id == -1
517 || desired_stop_thread_id == item.thread_id)
518 {
4ef367bf
TT
519 DEBUG_EVENTS ("pending stop anticipated, desired=0x%x, item=0x%x",
520 desired_stop_thread_id, item.thread_id);
e758e19c
TT
521 return true;
522 }
523 }
524
525 return false;
526}
527
528/* See nat/windows-nat.h. */
529
d2977bc4
TT
530gdb::optional<pending_stop>
531fetch_pending_stop (bool debug_events)
532{
533 gdb::optional<pending_stop> result;
534 for (auto iter = pending_stops.begin ();
535 iter != pending_stops.end ();
536 ++iter)
537 {
538 if (desired_stop_thread_id == -1
539 || desired_stop_thread_id == iter->thread_id)
540 {
541 result = *iter;
542 current_event = iter->event;
543
4ef367bf
TT
544 DEBUG_EVENTS ("pending stop found in 0x%x (desired=0x%x)",
545 iter->thread_id, desired_stop_thread_id);
d2977bc4
TT
546
547 pending_stops.erase (iter);
548 break;
549 }
550 }
551
552 return result;
553}
554
555/* See nat/windows-nat.h. */
556
e758e19c
TT
557BOOL
558continue_last_debug_event (DWORD continue_status, bool debug_events)
559{
4ef367bf
TT
560 DEBUG_EVENTS ("ContinueDebugEvent (cpid=%d, ctid=0x%x, %s)",
561 (unsigned) last_wait_event.dwProcessId,
562 (unsigned) last_wait_event.dwThreadId,
563 continue_status == DBG_CONTINUE ?
564 "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED");
e758e19c
TT
565
566 return ContinueDebugEvent (last_wait_event.dwProcessId,
567 last_wait_event.dwThreadId,
568 continue_status);
569}
570
2c1d95e8
TT
571/* See nat/windows-nat.h. */
572
573BOOL
574wait_for_debug_event (DEBUG_EVENT *event, DWORD timeout)
575{
576 BOOL result = WaitForDebugEvent (event, timeout);
577 if (result)
578 last_wait_event = *event;
579 return result;
580}
e758e19c 581
9e439f00
TT
582/* Define dummy functions which always return error for the rare cases where
583 these functions could not be found. */
584template<typename... T>
585BOOL WINAPI
586bad (T... args)
587{
588 return FALSE;
589}
590
591template<typename... T>
592DWORD WINAPI
593bad (T... args)
594{
595 return 0;
596}
597
598static BOOL WINAPI
599bad_GetCurrentConsoleFont (HANDLE w, BOOL bMaxWindow, CONSOLE_FONT_INFO *f)
600{
601 f->nFont = 0;
602 return 1;
603}
604
605static COORD WINAPI
606bad_GetConsoleFontSize (HANDLE w, DWORD nFont)
607{
608 COORD size;
609 size.X = 8;
610 size.Y = 12;
611 return size;
612}
613
614/* See windows-nat.h. */
615
616bool
617initialize_loadable ()
618{
619 bool result = true;
620 HMODULE hm = NULL;
621
622#define GPA(m, func) \
623 func = (func ## _ftype *) GetProcAddress (m, #func)
624
625 hm = LoadLibrary (TEXT ("kernel32.dll"));
626 if (hm)
627 {
628 GPA (hm, DebugActiveProcessStop);
629 GPA (hm, DebugBreakProcess);
630 GPA (hm, DebugSetProcessKillOnExit);
631 GPA (hm, GetConsoleFontSize);
632 GPA (hm, DebugActiveProcessStop);
633 GPA (hm, GetCurrentConsoleFont);
634#ifdef __x86_64__
635 GPA (hm, Wow64SuspendThread);
636 GPA (hm, Wow64GetThreadContext);
637 GPA (hm, Wow64SetThreadContext);
638 GPA (hm, Wow64GetThreadSelectorEntry);
639#endif
de071872 640 GPA (hm, GenerateConsoleCtrlEvent);
9e439f00
TT
641 }
642
643 /* Set variables to dummy versions of these processes if the function
644 wasn't found in kernel32.dll. */
645 if (!DebugBreakProcess)
646 DebugBreakProcess = bad;
647 if (!DebugActiveProcessStop || !DebugSetProcessKillOnExit)
648 {
649 DebugActiveProcessStop = bad;
650 DebugSetProcessKillOnExit = bad;
651 }
652 if (!GetConsoleFontSize)
653 GetConsoleFontSize = bad_GetConsoleFontSize;
654 if (!GetCurrentConsoleFont)
655 GetCurrentConsoleFont = bad_GetCurrentConsoleFont;
656
657 /* Load optional functions used for retrieving filename information
658 associated with the currently debugged process or its dlls. */
659 hm = LoadLibrary (TEXT ("psapi.dll"));
660 if (hm)
661 {
662 GPA (hm, EnumProcessModules);
663#ifdef __x86_64__
664 GPA (hm, EnumProcessModulesEx);
665#endif
666 GPA (hm, GetModuleInformation);
667 GPA (hm, GetModuleFileNameExA);
668 GPA (hm, GetModuleFileNameExW);
669 }
670
671 if (!EnumProcessModules || !GetModuleInformation
672 || !GetModuleFileNameExA || !GetModuleFileNameExW)
673 {
674 /* Set variables to dummy versions of these processes if the function
675 wasn't found in psapi.dll. */
676 EnumProcessModules = bad;
677 GetModuleInformation = bad;
678 GetModuleFileNameExA = bad;
679 GetModuleFileNameExW = bad;
680
681 result = false;
682 }
683
684 hm = LoadLibrary (TEXT ("advapi32.dll"));
685 if (hm)
686 {
687 GPA (hm, OpenProcessToken);
688 GPA (hm, LookupPrivilegeValueA);
689 GPA (hm, AdjustTokenPrivileges);
690 /* Only need to set one of these since if OpenProcessToken fails nothing
691 else is needed. */
692 if (!OpenProcessToken || !LookupPrivilegeValueA
693 || !AdjustTokenPrivileges)
694 OpenProcessToken = bad;
695 }
696
697#undef GPA
698
699 return result;
700}
701
4834dad0 702}