1 /* Internal interfaces for the Windows code
2 Copyright (C) 1995-2022 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"
22 #include "target/target.h"
24 #undef GetModuleFileNameEx
27 #define GetModuleFileNameEx GetModuleFileNameExA
29 #include <sys/cygwin.h>
31 typedef wchar_t cygwin_buf_t
;
32 #define GetModuleFileNameEx GetModuleFileNameExW
38 /* The most recent event from WaitForDebugEvent. Unlike
39 current_event, this is guaranteed never to come from a pending
40 stop. This is important because only data from the most recent
41 event from WaitForDebugEvent can be used when calling
42 ContinueDebugEvent. */
43 static DEBUG_EVENT last_wait_event
;
45 AdjustTokenPrivileges_ftype
*AdjustTokenPrivileges
;
46 DebugActiveProcessStop_ftype
*DebugActiveProcessStop
;
47 DebugBreakProcess_ftype
*DebugBreakProcess
;
48 DebugSetProcessKillOnExit_ftype
*DebugSetProcessKillOnExit
;
49 EnumProcessModules_ftype
*EnumProcessModules
;
51 EnumProcessModulesEx_ftype
*EnumProcessModulesEx
;
53 GetModuleInformation_ftype
*GetModuleInformation
;
54 GetModuleFileNameExA_ftype
*GetModuleFileNameExA
;
55 GetModuleFileNameExW_ftype
*GetModuleFileNameExW
;
56 LookupPrivilegeValueA_ftype
*LookupPrivilegeValueA
;
57 OpenProcessToken_ftype
*OpenProcessToken
;
58 GetCurrentConsoleFont_ftype
*GetCurrentConsoleFont
;
59 GetConsoleFontSize_ftype
*GetConsoleFontSize
;
61 Wow64SuspendThread_ftype
*Wow64SuspendThread
;
62 Wow64GetThreadContext_ftype
*Wow64GetThreadContext
;
63 Wow64SetThreadContext_ftype
*Wow64SetThreadContext
;
64 Wow64GetThreadSelectorEntry_ftype
*Wow64GetThreadSelectorEntry
;
66 GenerateConsoleCtrlEvent_ftype
*GenerateConsoleCtrlEvent
;
68 #define GetThreadDescription dyn_GetThreadDescription
69 typedef HRESULT
WINAPI (GetThreadDescription_ftype
) (HANDLE
, PWSTR
*);
70 static GetThreadDescription_ftype
*GetThreadDescription
;
72 /* Note that 'debug_events' must be locally defined in the relevant
74 #define DEBUG_EVENTS(fmt, ...) \
75 debug_prefixed_printf_cond (debug_events, "windows events", fmt, \
79 windows_thread_info::suspend ()
84 if (SuspendThread (h
) == (DWORD
) -1)
86 DWORD err
= GetLastError ();
88 /* We get Access Denied (5) when trying to suspend
89 threads that Windows started on behalf of the
90 debuggee, usually when those threads are just
92 We can get Invalid Handle (6) if the main thread
94 if (err
!= ERROR_INVALID_HANDLE
&& err
!= ERROR_ACCESS_DENIED
)
95 warning (_("SuspendThread (tid=0x%x) failed. (winerr %u)"),
96 (unsigned) tid
, (unsigned) err
);
104 windows_thread_info::resume ()
108 stopped_at_software_breakpoint
= false;
110 if (ResumeThread (h
) == (DWORD
) -1)
112 DWORD err
= GetLastError ();
113 warning (_("warning: ResumeThread (tid=0x%x) failed. (winerr %u)"),
114 (unsigned) tid
, (unsigned) err
);
121 windows_thread_info::thread_name ()
123 if (GetThreadDescription
!= nullptr)
126 HRESULT result
= GetThreadDescription (h
, &value
);
127 if (SUCCEEDED (result
))
129 int needed
= WideCharToMultiByte (CP_ACP
, 0, value
, -1, nullptr, 0,
133 /* USED_DEFAULT is how we detect that the encoding
134 conversion had to fall back to the substitution
135 character. It seems better to just reject bad
137 BOOL used_default
= FALSE
;
138 gdb::unique_xmalloc_ptr
<char> new_name
139 ((char *) xmalloc (needed
));
140 if (WideCharToMultiByte (CP_ACP
, 0, value
, -1,
141 new_name
.get (), needed
,
142 nullptr, &used_default
) == needed
144 && strlen (new_name
.get ()) > 0)
145 name
= std::move (new_name
);
154 /* Try to determine the executable filename.
156 EXE_NAME_RET is a pointer to a buffer whose size is EXE_NAME_MAX_LEN.
158 Upon success, the filename is stored inside EXE_NAME_RET, and
159 this function returns nonzero.
161 Otherwise, this function returns zero and the contents of
162 EXE_NAME_RET is undefined. */
165 windows_process_info::get_exec_module_filename (char *exe_name_ret
,
166 size_t exe_name_max_len
)
176 if (!EnumProcessModulesEx (handle
,
177 &dh_buf
, sizeof (HMODULE
), &cbNeeded
,
185 if (!EnumProcessModules (handle
,
186 &dh_buf
, sizeof (HMODULE
), &cbNeeded
)
191 /* We know the executable is always first in the list of modules,
192 which we just fetched. So no need to fetch more. */
196 /* Cygwin prefers that the path be in /x/y/z format, so extract
197 the filename into a temporary buffer first, and then convert it
198 to POSIX format into the destination buffer. */
199 cygwin_buf_t
*pathbuf
= (cygwin_buf_t
*) alloca (exe_name_max_len
* sizeof (cygwin_buf_t
));
201 len
= GetModuleFileNameEx (handle
,
202 dh_buf
, pathbuf
, exe_name_max_len
);
204 error (_("Error getting executable filename: %u."),
205 (unsigned) GetLastError ());
206 if (cygwin_conv_path (CCP_WIN_W_TO_POSIX
, pathbuf
, exe_name_ret
,
207 exe_name_max_len
) < 0)
208 error (_("Error converting executable filename to POSIX: %d."), errno
);
211 len
= GetModuleFileNameEx (handle
,
212 dh_buf
, exe_name_ret
, exe_name_max_len
);
214 error (_("Error getting executable filename: %u."),
215 (unsigned) GetLastError ());
218 return 1; /* success */
222 windows_process_info::pid_to_exec_file (int pid
)
224 static char path
[MAX_PATH
];
226 /* Try to find exe name as symlink target of /proc/<pid>/exe. */
228 char procexe
[sizeof ("/proc/4294967295/exe")];
230 xsnprintf (procexe
, sizeof (procexe
), "/proc/%u/exe", pid
);
231 nchars
= readlink (procexe
, path
, sizeof(path
));
232 if (nchars
> 0 && nchars
< sizeof (path
))
234 path
[nchars
] = '\0'; /* Got it */
239 /* If we get here then either Cygwin is hosed, this isn't a Cygwin version
240 of gdb, or we're trying to debug a non-Cygwin windows executable. */
241 if (!get_exec_module_filename (path
, sizeof (path
)))
247 /* Return the name of the DLL referenced by H at ADDRESS. UNICODE
248 determines what sort of string is read from the inferior. Returns
249 the name of the DLL, or NULL on error. If a name is returned, it
250 is stored in a static buffer which is valid until the next call to
254 get_image_name (HANDLE h
, void *address
, int unicode
)
257 static char buf
[MAX_PATH
];
259 static char buf
[(2 * MAX_PATH
) + 1];
261 DWORD size
= unicode
? sizeof (WCHAR
) : sizeof (char);
267 /* Attempt to read the name of the dll that was detected.
268 This is documented to work only when actively debugging
269 a program. It will not work for attached processes. */
273 /* See if we could read the address of a string, and that the
274 address isn't null. */
275 if (!ReadProcessMemory (h
, address
, &address_ptr
,
276 sizeof (address_ptr
), &done
)
277 || done
!= sizeof (address_ptr
)
281 /* Find the length of the string. */
282 while (ReadProcessMemory (h
, address_ptr
+ len
++ * size
, &b
, size
, &done
)
283 && (b
[0] != 0 || b
[size
- 1] != 0) && done
== size
)
287 ReadProcessMemory (h
, address_ptr
, buf
, len
, &done
);
290 WCHAR
*unicode_address
= (WCHAR
*) alloca (len
* sizeof (WCHAR
));
291 ReadProcessMemory (h
, address_ptr
, unicode_address
, len
* sizeof (WCHAR
),
294 wcstombs (buf
, unicode_address
, MAX_PATH
);
296 WideCharToMultiByte (CP_ACP
, 0, unicode_address
, len
, buf
, sizeof buf
,
304 /* See nat/windows-nat.h. */
307 windows_process_info::handle_ms_vc_exception (const EXCEPTION_RECORD
*rec
)
309 if (rec
->NumberParameters
>= 3
310 && (rec
->ExceptionInformation
[0] & 0xffffffff) == 0x1000)
312 DWORD named_thread_id
;
313 windows_thread_info
*named_thread
;
314 CORE_ADDR thread_name_target
;
316 thread_name_target
= rec
->ExceptionInformation
[1];
317 named_thread_id
= (DWORD
) (0xffffffff & rec
->ExceptionInformation
[2]);
319 if (named_thread_id
== (DWORD
) -1)
320 named_thread_id
= current_event
.dwThreadId
;
322 named_thread
= thread_rec (ptid_t (current_event
.dwProcessId
,
324 DONT_INVALIDATE_CONTEXT
);
325 if (named_thread
!= NULL
)
328 gdb::unique_xmalloc_ptr
<char> thread_name
329 = target_read_string (thread_name_target
, 1025, &thread_name_len
);
330 if (thread_name_len
> 0)
332 thread_name
.get ()[thread_name_len
- 1] = '\0';
333 named_thread
->name
= std::move (thread_name
);
343 /* The exception thrown by a program to tell the debugger the name of
344 a thread. The exception record contains an ID of a thread and a
345 name to give it. This exception has no documented name, but MSDN
346 dubs it "MS_VC_EXCEPTION" in one code example. */
347 #define MS_VC_EXCEPTION 0x406d1388
349 handle_exception_result
350 windows_process_info::handle_exception (struct target_waitstatus
*ourstatus
,
351 bool debug_exceptions
)
353 #define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \
354 debug_printf ("gdb: Target exception %s at %s\n", x, \
355 host_address_to_string (\
356 current_event.u.Exception.ExceptionRecord.ExceptionAddress))
358 EXCEPTION_RECORD
*rec
= ¤t_event
.u
.Exception
.ExceptionRecord
;
359 DWORD code
= rec
->ExceptionCode
;
360 handle_exception_result result
= HANDLE_EXCEPTION_HANDLED
;
362 memcpy (&siginfo_er
, rec
, sizeof siginfo_er
);
364 /* Record the context of the current thread. */
365 thread_rec (ptid_t (current_event
.dwProcessId
, current_event
.dwThreadId
, 0),
368 last_sig
= GDB_SIGNAL_0
;
372 case EXCEPTION_ACCESS_VIOLATION
:
373 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
374 ourstatus
->set_stopped (GDB_SIGNAL_SEGV
);
375 if (handle_access_violation (rec
))
376 return HANDLE_EXCEPTION_UNHANDLED
;
378 case STATUS_STACK_OVERFLOW
:
379 DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
380 ourstatus
->set_stopped (GDB_SIGNAL_SEGV
);
382 case STATUS_FLOAT_DENORMAL_OPERAND
:
383 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
384 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
386 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
387 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
388 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
390 case STATUS_FLOAT_INEXACT_RESULT
:
391 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
392 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
394 case STATUS_FLOAT_INVALID_OPERATION
:
395 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
396 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
398 case STATUS_FLOAT_OVERFLOW
:
399 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
400 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
402 case STATUS_FLOAT_STACK_CHECK
:
403 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
404 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
406 case STATUS_FLOAT_UNDERFLOW
:
407 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
408 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
410 case STATUS_FLOAT_DIVIDE_BY_ZERO
:
411 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
412 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
414 case STATUS_INTEGER_DIVIDE_BY_ZERO
:
415 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
416 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
418 case STATUS_INTEGER_OVERFLOW
:
419 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
420 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
422 case EXCEPTION_BREAKPOINT
:
424 if (ignore_first_breakpoint
)
426 /* For WOW64 processes, there are always 2 breakpoint exceptions
427 on startup, first a BREAKPOINT for the 64bit ntdll.dll,
428 then a WX86_BREAKPOINT for the 32bit ntdll.dll.
429 Here we only care about the WX86_BREAKPOINT's. */
430 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT - ignore_first_breakpoint");
431 ourstatus
->set_spurious ();
432 ignore_first_breakpoint
= false;
435 else if (wow64_process
)
437 /* This breakpoint exception is triggered for WOW64 processes when
438 reaching an int3 instruction in 64bit code.
439 gdb checks for int3 in case of SIGTRAP, this fails because
440 Wow64GetThreadContext can only report the pc of 32bit code, and
441 gdb lets the target process continue.
442 So handle it as SIGINT instead, then the target is stopped
444 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT - wow64_process");
445 rec
->ExceptionCode
= DBG_CONTROL_C
;
446 ourstatus
->set_stopped (GDB_SIGNAL_INT
);
451 case STATUS_WX86_BREAKPOINT
:
452 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
453 ourstatus
->set_stopped (GDB_SIGNAL_TRAP
);
456 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
457 ourstatus
->set_stopped (GDB_SIGNAL_INT
);
459 case DBG_CONTROL_BREAK
:
460 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
461 ourstatus
->set_stopped (GDB_SIGNAL_INT
);
463 case EXCEPTION_SINGLE_STEP
:
464 case STATUS_WX86_SINGLE_STEP
:
465 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
466 ourstatus
->set_stopped (GDB_SIGNAL_TRAP
);
468 case EXCEPTION_ILLEGAL_INSTRUCTION
:
469 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
470 ourstatus
->set_stopped (GDB_SIGNAL_ILL
);
472 case EXCEPTION_PRIV_INSTRUCTION
:
473 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
474 ourstatus
->set_stopped (GDB_SIGNAL_ILL
);
476 case EXCEPTION_NONCONTINUABLE_EXCEPTION
:
477 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
478 ourstatus
->set_stopped (GDB_SIGNAL_ILL
);
480 case MS_VC_EXCEPTION
:
481 DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION");
482 if (handle_ms_vc_exception (rec
))
484 ourstatus
->set_stopped (GDB_SIGNAL_TRAP
);
485 result
= HANDLE_EXCEPTION_IGNORED
;
488 /* treat improperly formed exception as unknown */
491 /* Treat unhandled first chance exceptions specially. */
492 if (current_event
.u
.Exception
.dwFirstChance
)
493 return HANDLE_EXCEPTION_UNHANDLED
;
494 debug_printf ("gdb: unknown target exception 0x%08x at %s\n",
495 (unsigned) current_event
.u
.Exception
.ExceptionRecord
.ExceptionCode
,
496 host_address_to_string (
497 current_event
.u
.Exception
.ExceptionRecord
.ExceptionAddress
));
498 ourstatus
->set_stopped (GDB_SIGNAL_UNKNOWN
);
502 if (ourstatus
->kind () == TARGET_WAITKIND_STOPPED
)
503 last_sig
= ourstatus
->sig ();
507 #undef DEBUG_EXCEPTION_SIMPLE
510 /* See nat/windows-nat.h. */
513 windows_process_info::add_dll (LPVOID load_addr
)
515 HMODULE dummy_hmodule
;
523 if (EnumProcessModulesEx (handle
, &dummy_hmodule
,
524 sizeof (HMODULE
), &cb_needed
,
525 LIST_MODULES_32BIT
) == 0)
531 if (EnumProcessModules (handle
, &dummy_hmodule
,
532 sizeof (HMODULE
), &cb_needed
) == 0)
539 hmodules
= (HMODULE
*) alloca (cb_needed
);
543 if (EnumProcessModulesEx (handle
, hmodules
,
544 cb_needed
, &cb_needed
,
545 LIST_MODULES_32BIT
) == 0)
551 if (EnumProcessModules (handle
, hmodules
,
552 cb_needed
, &cb_needed
) == 0)
556 char system_dir
[MAX_PATH
];
557 char syswow_dir
[MAX_PATH
];
558 size_t system_dir_len
= 0;
559 bool convert_syswow_dir
= false;
564 /* This fails on 32bit Windows because it has no SysWOW64 directory,
565 and in this case a path conversion isn't necessary. */
566 UINT len
= GetSystemWow64DirectoryA (syswow_dir
, sizeof (syswow_dir
));
569 /* Check that we have passed a large enough buffer. */
570 gdb_assert (len
< sizeof (syswow_dir
));
572 len
= GetSystemDirectoryA (system_dir
, sizeof (system_dir
));
574 gdb_assert (len
!= 0);
575 /* Check that we have passed a large enough buffer. */
576 gdb_assert (len
< sizeof (system_dir
));
578 strcat (system_dir
, "\\");
579 strcat (syswow_dir
, "\\");
580 system_dir_len
= strlen (system_dir
);
582 convert_syswow_dir
= true;
586 for (i
= 1; i
< (int) (cb_needed
/ sizeof (HMODULE
)); i
++)
590 wchar_t dll_name
[MAX_PATH
];
591 char dll_name_mb
[MAX_PATH
];
593 char dll_name
[MAX_PATH
];
596 if (GetModuleInformation (handle
, hmodules
[i
],
597 &mi
, sizeof (mi
)) == 0)
600 if (GetModuleFileNameEx (handle
, hmodules
[i
],
601 dll_name
, sizeof (dll_name
)) == 0)
604 wcstombs (dll_name_mb
, dll_name
, MAX_PATH
);
609 /* Convert the DLL path of 32bit processes returned by
610 GetModuleFileNameEx from the 64bit system directory to the
611 32bit syswow64 directory if necessary. */
612 std::string syswow_dll_path
;
613 if (convert_syswow_dir
614 && strncasecmp (name
, system_dir
, system_dir_len
) == 0
615 && strchr (name
+ system_dir_len
, '\\') == nullptr)
617 syswow_dll_path
= syswow_dir
;
618 syswow_dll_path
+= name
+ system_dir_len
;
619 name
= syswow_dll_path
.c_str();
622 /* Record the DLL if either LOAD_ADDR is NULL or the address
623 at which the DLL was loaded is equal to LOAD_ADDR. */
624 if (!(load_addr
!= nullptr && mi
.lpBaseOfDll
!= load_addr
))
626 handle_load_dll (name
, mi
.lpBaseOfDll
);
627 if (load_addr
!= nullptr)
633 /* See nat/windows-nat.h. */
636 windows_process_info::dll_loaded_event ()
638 gdb_assert (current_event
.dwDebugEventCode
== LOAD_DLL_DEBUG_EVENT
);
640 LOAD_DLL_DEBUG_INFO
*event
= ¤t_event
.u
.LoadDll
;
641 const char *dll_name
;
643 /* Try getting the DLL name via the lpImageName field of the event.
644 Note that Microsoft documents this fields as strictly optional,
645 in the sense that it might be NULL. And the first DLL event in
646 particular is explicitly documented as "likely not pass[ed]"
647 (source: MSDN LOAD_DLL_DEBUG_INFO structure). */
648 dll_name
= get_image_name (handle
, event
->lpImageName
, event
->fUnicode
);
649 /* If the DLL name could not be gleaned via lpImageName, try harder
650 by enumerating all the DLLs loaded into the inferior, looking for
651 one that is loaded at base address = lpBaseOfDll. */
652 if (dll_name
!= nullptr)
653 handle_load_dll (dll_name
, event
->lpBaseOfDll
);
654 else if (event
->lpBaseOfDll
!= nullptr)
655 add_dll (event
->lpBaseOfDll
);
658 /* See nat/windows-nat.h. */
661 windows_process_info::add_all_dlls ()
666 /* See nat/windows-nat.h. */
669 windows_process_info::matching_pending_stop (bool debug_events
)
671 /* If there are pending stops, and we might plausibly hit one of
672 them, we don't want to actually continue the inferior -- we just
673 want to report the stop. In this case, we just pretend to
674 continue. See the comment by the definition of "pending_stops"
675 for details on why this is needed. */
676 for (const auto &item
: pending_stops
)
678 if (desired_stop_thread_id
== -1
679 || desired_stop_thread_id
== item
.thread_id
)
681 DEBUG_EVENTS ("pending stop anticipated, desired=0x%x, item=0x%x",
682 desired_stop_thread_id
, item
.thread_id
);
690 /* See nat/windows-nat.h. */
692 gdb::optional
<pending_stop
>
693 windows_process_info::fetch_pending_stop (bool debug_events
)
695 gdb::optional
<pending_stop
> result
;
696 for (auto iter
= pending_stops
.begin ();
697 iter
!= pending_stops
.end ();
700 if (desired_stop_thread_id
== -1
701 || desired_stop_thread_id
== iter
->thread_id
)
704 current_event
= iter
->event
;
706 DEBUG_EVENTS ("pending stop found in 0x%x (desired=0x%x)",
707 iter
->thread_id
, desired_stop_thread_id
);
709 pending_stops
.erase (iter
);
717 /* See nat/windows-nat.h. */
720 continue_last_debug_event (DWORD continue_status
, bool debug_events
)
722 DEBUG_EVENTS ("ContinueDebugEvent (cpid=%d, ctid=0x%x, %s)",
723 (unsigned) last_wait_event
.dwProcessId
,
724 (unsigned) last_wait_event
.dwThreadId
,
725 continue_status
== DBG_CONTINUE
?
726 "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED");
728 return ContinueDebugEvent (last_wait_event
.dwProcessId
,
729 last_wait_event
.dwThreadId
,
733 /* See nat/windows-nat.h. */
736 wait_for_debug_event (DEBUG_EVENT
*event
, DWORD timeout
)
738 BOOL result
= WaitForDebugEvent (event
, timeout
);
740 last_wait_event
= *event
;
744 /* Define dummy functions which always return error for the rare cases where
745 these functions could not be found. */
746 template<typename
... T
>
753 template<typename
... T
>
761 bad_GetCurrentConsoleFont (HANDLE w
, BOOL bMaxWindow
, CONSOLE_FONT_INFO
*f
)
768 bad_GetConsoleFontSize (HANDLE w
, DWORD nFont
)
776 /* See windows-nat.h. */
779 initialize_loadable ()
784 #define GPA(m, func) \
785 func = (func ## _ftype *) GetProcAddress (m, #func)
787 hm
= LoadLibrary (TEXT ("kernel32.dll"));
790 GPA (hm
, DebugActiveProcessStop
);
791 GPA (hm
, DebugBreakProcess
);
792 GPA (hm
, DebugSetProcessKillOnExit
);
793 GPA (hm
, GetConsoleFontSize
);
794 GPA (hm
, DebugActiveProcessStop
);
795 GPA (hm
, GetCurrentConsoleFont
);
797 GPA (hm
, Wow64SuspendThread
);
798 GPA (hm
, Wow64GetThreadContext
);
799 GPA (hm
, Wow64SetThreadContext
);
800 GPA (hm
, Wow64GetThreadSelectorEntry
);
802 GPA (hm
, GenerateConsoleCtrlEvent
);
803 GPA (hm
, GetThreadDescription
);
806 /* Set variables to dummy versions of these processes if the function
807 wasn't found in kernel32.dll. */
808 if (!DebugBreakProcess
)
809 DebugBreakProcess
= bad
;
810 if (!DebugActiveProcessStop
|| !DebugSetProcessKillOnExit
)
812 DebugActiveProcessStop
= bad
;
813 DebugSetProcessKillOnExit
= bad
;
815 if (!GetConsoleFontSize
)
816 GetConsoleFontSize
= bad_GetConsoleFontSize
;
817 if (!GetCurrentConsoleFont
)
818 GetCurrentConsoleFont
= bad_GetCurrentConsoleFont
;
820 /* Load optional functions used for retrieving filename information
821 associated with the currently debugged process or its dlls. */
822 hm
= LoadLibrary (TEXT ("psapi.dll"));
825 GPA (hm
, EnumProcessModules
);
827 GPA (hm
, EnumProcessModulesEx
);
829 GPA (hm
, GetModuleInformation
);
830 GPA (hm
, GetModuleFileNameExA
);
831 GPA (hm
, GetModuleFileNameExW
);
834 if (!EnumProcessModules
|| !GetModuleInformation
835 || !GetModuleFileNameExA
|| !GetModuleFileNameExW
)
837 /* Set variables to dummy versions of these processes if the function
838 wasn't found in psapi.dll. */
839 EnumProcessModules
= bad
;
840 GetModuleInformation
= bad
;
841 GetModuleFileNameExA
= bad
;
842 GetModuleFileNameExW
= bad
;
847 hm
= LoadLibrary (TEXT ("advapi32.dll"));
850 GPA (hm
, OpenProcessToken
);
851 GPA (hm
, LookupPrivilegeValueA
);
852 GPA (hm
, AdjustTokenPrivileges
);
853 /* Only need to set one of these since if OpenProcessToken fails nothing
855 if (!OpenProcessToken
|| !LookupPrivilegeValueA
856 || !AdjustTokenPrivileges
)
857 OpenProcessToken
= bad
;
860 /* On some versions of Windows, this function is only available in
861 KernelBase.dll, not kernel32.dll. */
862 if (GetThreadDescription
== nullptr)
864 hm
= LoadLibrary (TEXT ("KernelBase.dll"));
866 GPA (hm
, GetThreadDescription
);