1 /* Internal interfaces for the Windows code
2 Copyright (C) 1995-2025 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 "nat/windows-nat.h"
20 #include "gdbsupport/common-debug.h"
21 #include "target/target.h"
23 #undef GetModuleFileNameEx
26 #define GetModuleFileNameEx GetModuleFileNameExA
28 #include <sys/cygwin.h>
30 #define GetModuleFileNameEx GetModuleFileNameExW
36 /* The most recent event from WaitForDebugEvent. Unlike
37 current_event, this is guaranteed never to come from a pending
38 stop. This is important because only data from the most recent
39 event from WaitForDebugEvent can be used when calling
40 ContinueDebugEvent. */
41 static DEBUG_EVENT last_wait_event
;
43 AdjustTokenPrivileges_ftype
*AdjustTokenPrivileges
;
44 DebugActiveProcessStop_ftype
*DebugActiveProcessStop
;
45 DebugBreakProcess_ftype
*DebugBreakProcess
;
46 DebugSetProcessKillOnExit_ftype
*DebugSetProcessKillOnExit
;
47 EnumProcessModules_ftype
*EnumProcessModules
;
49 EnumProcessModulesEx_ftype
*EnumProcessModulesEx
;
51 GetModuleInformation_ftype
*GetModuleInformation
;
52 GetModuleFileNameExA_ftype
*GetModuleFileNameExA
;
53 GetModuleFileNameExW_ftype
*GetModuleFileNameExW
;
54 LookupPrivilegeValueA_ftype
*LookupPrivilegeValueA
;
55 OpenProcessToken_ftype
*OpenProcessToken
;
56 GetCurrentConsoleFont_ftype
*GetCurrentConsoleFont
;
57 GetConsoleFontSize_ftype
*GetConsoleFontSize
;
59 Wow64SuspendThread_ftype
*Wow64SuspendThread
;
60 Wow64GetThreadContext_ftype
*Wow64GetThreadContext
;
61 Wow64SetThreadContext_ftype
*Wow64SetThreadContext
;
62 Wow64GetThreadSelectorEntry_ftype
*Wow64GetThreadSelectorEntry
;
64 GenerateConsoleCtrlEvent_ftype
*GenerateConsoleCtrlEvent
;
66 #define GetThreadDescription dyn_GetThreadDescription
67 typedef HRESULT
WINAPI (GetThreadDescription_ftype
) (HANDLE
, PWSTR
*);
68 static GetThreadDescription_ftype
*GetThreadDescription
;
70 InitializeProcThreadAttributeList_ftype
*InitializeProcThreadAttributeList
;
71 UpdateProcThreadAttribute_ftype
*UpdateProcThreadAttribute
;
72 DeleteProcThreadAttributeList_ftype
*DeleteProcThreadAttributeList
;
74 /* Note that 'debug_events' must be locally defined in the relevant
76 #define DEBUG_EVENTS(fmt, ...) \
77 debug_prefixed_printf_cond (debug_events, "windows events", fmt, \
81 windows_thread_info::suspend ()
86 if (SuspendThread (h
) == (DWORD
) -1)
88 DWORD err
= GetLastError ();
90 /* We get Access Denied (5) when trying to suspend
91 threads that Windows started on behalf of the
92 debuggee, usually when those threads are just
94 We can get Invalid Handle (6) if the main thread
96 if (err
!= ERROR_INVALID_HANDLE
&& err
!= ERROR_ACCESS_DENIED
)
97 warning (_("SuspendThread (tid=0x%x) failed. (winerr %u: %s)"),
98 (unsigned) tid
, (unsigned) err
, strwinerror (err
));
106 windows_thread_info::resume ()
110 stopped_at_software_breakpoint
= false;
112 if (ResumeThread (h
) == (DWORD
) -1)
114 DWORD err
= GetLastError ();
115 warning (_("warning: ResumeThread (tid=0x%x) failed. (winerr %u: %s)"),
116 (unsigned) tid
, (unsigned) err
, strwinerror (err
));
123 windows_thread_info::thread_name ()
125 if (GetThreadDescription
!= nullptr)
128 HRESULT result
= GetThreadDescription (h
, &value
);
129 if (SUCCEEDED (result
))
131 int needed
= WideCharToMultiByte (CP_ACP
, 0, value
, -1, nullptr, 0,
135 /* USED_DEFAULT is how we detect that the encoding
136 conversion had to fall back to the substitution
137 character. It seems better to just reject bad
139 BOOL used_default
= FALSE
;
140 gdb::unique_xmalloc_ptr
<char> new_name
141 ((char *) xmalloc (needed
));
142 if (WideCharToMultiByte (CP_ACP
, 0, value
, -1,
143 new_name
.get (), needed
,
144 nullptr, &used_default
) == needed
146 && strlen (new_name
.get ()) > 0)
147 name
= std::move (new_name
);
156 /* Try to determine the executable filename.
158 EXE_NAME_RET is a pointer to a buffer whose size is EXE_NAME_MAX_LEN.
160 Upon success, the filename is stored inside EXE_NAME_RET, and
161 this function returns nonzero.
163 Otherwise, this function returns zero and the contents of
164 EXE_NAME_RET is undefined. */
167 windows_process_info::get_exec_module_filename (char *exe_name_ret
,
168 size_t exe_name_max_len
)
175 BOOL ret
= with_context (nullptr, [&] (auto *context
)
177 return enum_process_modules (context
, handle
, &dh_buf
,
178 sizeof (HMODULE
), &cbNeeded
);
180 if (!ret
|| !cbNeeded
)
183 /* We know the executable is always first in the list of modules,
184 which we just fetched. So no need to fetch more. */
188 /* Cygwin prefers that the path be in /x/y/z format, so extract
189 the filename into a temporary buffer first, and then convert it
190 to POSIX format into the destination buffer. */
191 wchar_t *pathbuf
= (wchar_t *) alloca (exe_name_max_len
* sizeof (wchar_t));
193 len
= GetModuleFileNameEx (handle
,
194 dh_buf
, pathbuf
, exe_name_max_len
);
197 unsigned err
= (unsigned) GetLastError ();
198 throw_winerror_with_name (_("Error getting executable filename"), err
);
200 if (cygwin_conv_path (CCP_WIN_W_TO_POSIX
, pathbuf
, exe_name_ret
,
201 exe_name_max_len
) < 0)
202 error (_("Error converting executable filename to POSIX: %d."), errno
);
205 len
= GetModuleFileNameEx (handle
,
206 dh_buf
, exe_name_ret
, exe_name_max_len
);
209 unsigned err
= (unsigned) GetLastError ();
210 throw_winerror_with_name (_("Error getting executable filename"), err
);
214 return 1; /* success */
218 windows_process_info::pid_to_exec_file (int pid
)
220 static char path
[MAX_PATH
];
222 /* Try to find exe name as symlink target of /proc/<pid>/exe. */
224 char procexe
[sizeof ("/proc/4294967295/exe")];
226 xsnprintf (procexe
, sizeof (procexe
), "/proc/%u/exe", pid
);
227 nchars
= readlink (procexe
, path
, sizeof(path
));
228 if (nchars
> 0 && nchars
< sizeof (path
))
230 path
[nchars
] = '\0'; /* Got it */
235 /* If we get here then either Cygwin is hosed, this isn't a Cygwin version
236 of gdb, or we're trying to debug a non-Cygwin windows executable. */
237 if (!get_exec_module_filename (path
, sizeof (path
)))
243 /* Return the name of the DLL referenced by H at ADDRESS. UNICODE
244 determines what sort of string is read from the inferior. Returns
245 the name of the DLL, or NULL on error. If a name is returned, it
246 is stored in a static buffer which is valid until the next call to
250 get_image_name (HANDLE h
, void *address
, int unicode
)
253 static char buf
[MAX_PATH
];
255 static char buf
[(2 * MAX_PATH
) + 1];
257 DWORD size
= unicode
? sizeof (WCHAR
) : sizeof (char);
263 /* Attempt to read the name of the dll that was detected.
264 This is documented to work only when actively debugging
265 a program. It will not work for attached processes. */
269 /* See if we could read the address of a string, and that the
270 address isn't null. */
271 if (!ReadProcessMemory (h
, address
, &address_ptr
,
272 sizeof (address_ptr
), &done
)
273 || done
!= sizeof (address_ptr
)
277 /* Find the length of the string. */
278 while (ReadProcessMemory (h
, address_ptr
+ len
++ * size
, &b
, size
, &done
)
279 && (b
[0] != 0 || b
[size
- 1] != 0) && done
== size
)
283 ReadProcessMemory (h
, address_ptr
, buf
, len
, &done
);
286 WCHAR
*unicode_address
= (WCHAR
*) alloca (len
* sizeof (WCHAR
));
287 ReadProcessMemory (h
, address_ptr
, unicode_address
, len
* sizeof (WCHAR
),
290 wcstombs (buf
, unicode_address
, MAX_PATH
);
292 WideCharToMultiByte (CP_ACP
, 0, unicode_address
, len
, buf
, sizeof buf
,
300 /* See nat/windows-nat.h. */
303 windows_process_info::handle_ms_vc_exception (const EXCEPTION_RECORD
*rec
)
305 if (rec
->NumberParameters
>= 3
306 && (rec
->ExceptionInformation
[0] & 0xffffffff) == 0x1000)
308 DWORD named_thread_id
;
309 windows_thread_info
*named_thread
;
310 CORE_ADDR thread_name_target
;
312 thread_name_target
= rec
->ExceptionInformation
[1];
313 named_thread_id
= (DWORD
) (0xffffffff & rec
->ExceptionInformation
[2]);
315 if (named_thread_id
== (DWORD
) -1)
316 named_thread_id
= current_event
.dwThreadId
;
318 named_thread
= thread_rec (ptid_t (current_event
.dwProcessId
,
320 DONT_INVALIDATE_CONTEXT
);
321 if (named_thread
!= NULL
)
324 gdb::unique_xmalloc_ptr
<char> thread_name
325 = target_read_string (thread_name_target
, 1025, &thread_name_len
);
326 if (thread_name_len
> 0)
328 thread_name
.get ()[thread_name_len
- 1] = '\0';
329 named_thread
->name
= std::move (thread_name
);
339 /* The exception thrown by a program to tell the debugger the name of
340 a thread. The exception record contains an ID of a thread and a
341 name to give it. This exception has no documented name, but MSDN
342 dubs it "MS_VC_EXCEPTION" in one code example. */
343 #define MS_VC_EXCEPTION 0x406d1388
345 handle_exception_result
346 windows_process_info::handle_exception (struct target_waitstatus
*ourstatus
,
347 bool debug_exceptions
)
349 #define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \
350 debug_printf ("gdb: Target exception %s at %s\n", x, \
351 host_address_to_string (\
352 current_event.u.Exception.ExceptionRecord.ExceptionAddress))
354 EXCEPTION_RECORD
*rec
= ¤t_event
.u
.Exception
.ExceptionRecord
;
355 DWORD code
= rec
->ExceptionCode
;
356 handle_exception_result result
= HANDLE_EXCEPTION_HANDLED
;
358 memcpy (&siginfo_er
, rec
, sizeof siginfo_er
);
360 /* Record the context of the current thread. */
361 thread_rec (ptid_t (current_event
.dwProcessId
, current_event
.dwThreadId
, 0),
364 last_sig
= GDB_SIGNAL_0
;
368 case EXCEPTION_ACCESS_VIOLATION
:
369 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
370 ourstatus
->set_stopped (GDB_SIGNAL_SEGV
);
371 if (handle_access_violation (rec
))
372 return HANDLE_EXCEPTION_UNHANDLED
;
374 case STATUS_STACK_OVERFLOW
:
375 DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
376 ourstatus
->set_stopped (GDB_SIGNAL_SEGV
);
378 case STATUS_FLOAT_DENORMAL_OPERAND
:
379 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
380 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
382 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
383 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
384 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
386 case STATUS_FLOAT_INEXACT_RESULT
:
387 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
388 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
390 case STATUS_FLOAT_INVALID_OPERATION
:
391 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
392 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
394 case STATUS_FLOAT_OVERFLOW
:
395 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
396 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
398 case STATUS_FLOAT_STACK_CHECK
:
399 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
400 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
402 case STATUS_FLOAT_UNDERFLOW
:
403 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
404 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
406 case STATUS_FLOAT_DIVIDE_BY_ZERO
:
407 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
408 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
410 case STATUS_INTEGER_DIVIDE_BY_ZERO
:
411 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
412 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
414 case STATUS_INTEGER_OVERFLOW
:
415 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
416 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
418 case EXCEPTION_BREAKPOINT
:
420 if (ignore_first_breakpoint
)
422 /* For WOW64 processes, there are always 2 breakpoint exceptions
423 on startup, first a BREAKPOINT for the 64bit ntdll.dll,
424 then a WX86_BREAKPOINT for the 32bit ntdll.dll.
425 Here we only care about the WX86_BREAKPOINT's. */
426 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT - ignore_first_breakpoint");
427 ourstatus
->set_spurious ();
428 ignore_first_breakpoint
= false;
431 else if (wow64_process
)
433 /* This breakpoint exception is triggered for WOW64 processes when
434 reaching an int3 instruction in 64bit code.
435 gdb checks for int3 in case of SIGTRAP, this fails because
436 Wow64GetThreadContext can only report the pc of 32bit code, and
437 gdb lets the target process continue.
438 So handle it as SIGINT instead, then the target is stopped
440 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT - wow64_process");
441 rec
->ExceptionCode
= DBG_CONTROL_C
;
442 ourstatus
->set_stopped (GDB_SIGNAL_INT
);
447 case STATUS_WX86_BREAKPOINT
:
448 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
449 ourstatus
->set_stopped (GDB_SIGNAL_TRAP
);
452 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
453 ourstatus
->set_stopped (GDB_SIGNAL_INT
);
455 case DBG_CONTROL_BREAK
:
456 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
457 ourstatus
->set_stopped (GDB_SIGNAL_INT
);
459 case EXCEPTION_SINGLE_STEP
:
460 case STATUS_WX86_SINGLE_STEP
:
461 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
462 ourstatus
->set_stopped (GDB_SIGNAL_TRAP
);
464 case EXCEPTION_ILLEGAL_INSTRUCTION
:
465 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
466 ourstatus
->set_stopped (GDB_SIGNAL_ILL
);
468 case EXCEPTION_PRIV_INSTRUCTION
:
469 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
470 ourstatus
->set_stopped (GDB_SIGNAL_ILL
);
472 case EXCEPTION_NONCONTINUABLE_EXCEPTION
:
473 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
474 ourstatus
->set_stopped (GDB_SIGNAL_ILL
);
476 case MS_VC_EXCEPTION
:
477 DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION");
478 if (handle_ms_vc_exception (rec
))
480 ourstatus
->set_stopped (GDB_SIGNAL_TRAP
);
481 result
= HANDLE_EXCEPTION_IGNORED
;
484 /* treat improperly formed exception as unknown */
487 /* Treat unhandled first chance exceptions specially. */
488 if (current_event
.u
.Exception
.dwFirstChance
)
489 return HANDLE_EXCEPTION_UNHANDLED
;
490 debug_printf ("gdb: unknown target exception 0x%08x at %s\n",
491 (unsigned) current_event
.u
.Exception
.ExceptionRecord
.ExceptionCode
,
492 host_address_to_string (
493 current_event
.u
.Exception
.ExceptionRecord
.ExceptionAddress
));
494 ourstatus
->set_stopped (GDB_SIGNAL_UNKNOWN
);
498 if (ourstatus
->kind () == TARGET_WAITKIND_STOPPED
)
499 last_sig
= ourstatus
->sig ();
503 #undef DEBUG_EXCEPTION_SIMPLE
506 /* See nat/windows-nat.h. */
509 windows_process_info::add_dll (LPVOID load_addr
)
511 HMODULE dummy_hmodule
;
516 BOOL ret
= with_context (nullptr, [&] (auto *context
)
518 return enum_process_modules (context
, handle
, &dummy_hmodule
,
519 sizeof (HMODULE
), &cb_needed
);
521 if (!ret
|| cb_needed
< 1)
524 hmodules
= (HMODULE
*) alloca (cb_needed
);
525 ret
= with_context (nullptr, [&] (auto *context
)
527 return enum_process_modules (context
, handle
, hmodules
,
528 cb_needed
, &cb_needed
);
533 char system_dir
[MAX_PATH
];
534 char syswow_dir
[MAX_PATH
];
535 size_t system_dir_len
= 0;
536 bool convert_syswow_dir
= false;
541 /* This fails on 32bit Windows because it has no SysWOW64 directory,
542 and in this case a path conversion isn't necessary. */
543 UINT len
= GetSystemWow64DirectoryA (syswow_dir
, sizeof (syswow_dir
));
546 /* Check that we have passed a large enough buffer. */
547 gdb_assert (len
< sizeof (syswow_dir
));
549 len
= GetSystemDirectoryA (system_dir
, sizeof (system_dir
));
551 gdb_assert (len
!= 0);
552 /* Check that we have passed a large enough buffer. */
553 gdb_assert (len
< sizeof (system_dir
));
555 strcat (system_dir
, "\\");
556 strcat (syswow_dir
, "\\");
557 system_dir_len
= strlen (system_dir
);
559 convert_syswow_dir
= true;
563 for (i
= 1; i
< (int) (cb_needed
/ sizeof (HMODULE
)); i
++)
567 wchar_t dll_name
[MAX_PATH
];
568 char dll_name_mb
[MAX_PATH
];
570 char dll_name
[MAX_PATH
];
573 if (GetModuleInformation (handle
, hmodules
[i
],
574 &mi
, sizeof (mi
)) == 0)
577 if (GetModuleFileNameEx (handle
, hmodules
[i
],
578 dll_name
, sizeof (dll_name
)) == 0)
581 wcstombs (dll_name_mb
, dll_name
, MAX_PATH
);
586 /* Convert the DLL path of 32bit processes returned by
587 GetModuleFileNameEx from the 64bit system directory to the
588 32bit syswow64 directory if necessary. */
589 std::string syswow_dll_path
;
590 if (convert_syswow_dir
591 && strncasecmp (name
, system_dir
, system_dir_len
) == 0
592 && strchr (name
+ system_dir_len
, '\\') == nullptr)
594 syswow_dll_path
= syswow_dir
;
595 syswow_dll_path
+= name
+ system_dir_len
;
596 name
= syswow_dll_path
.c_str();
599 /* Record the DLL if either LOAD_ADDR is NULL or the address
600 at which the DLL was loaded is equal to LOAD_ADDR. */
601 if (!(load_addr
!= nullptr && mi
.lpBaseOfDll
!= load_addr
))
603 handle_load_dll (name
, mi
.lpBaseOfDll
);
604 if (load_addr
!= nullptr)
610 /* See nat/windows-nat.h. */
613 windows_process_info::dll_loaded_event ()
615 gdb_assert (current_event
.dwDebugEventCode
== LOAD_DLL_DEBUG_EVENT
);
617 LOAD_DLL_DEBUG_INFO
*event
= ¤t_event
.u
.LoadDll
;
618 const char *dll_name
;
620 /* Try getting the DLL name via the lpImageName field of the event.
621 Note that Microsoft documents this fields as strictly optional,
622 in the sense that it might be NULL. And the first DLL event in
623 particular is explicitly documented as "likely not pass[ed]"
624 (source: MSDN LOAD_DLL_DEBUG_INFO structure). */
625 dll_name
= get_image_name (handle
, event
->lpImageName
, event
->fUnicode
);
626 /* If the DLL name could not be gleaned via lpImageName, try harder
627 by enumerating all the DLLs loaded into the inferior, looking for
628 one that is loaded at base address = lpBaseOfDll. */
629 if (dll_name
!= nullptr)
630 handle_load_dll (dll_name
, event
->lpBaseOfDll
);
631 else if (event
->lpBaseOfDll
!= nullptr)
632 add_dll (event
->lpBaseOfDll
);
635 /* See nat/windows-nat.h. */
638 windows_process_info::add_all_dlls ()
643 /* See nat/windows-nat.h. */
646 windows_process_info::matching_pending_stop (bool debug_events
)
648 /* If there are pending stops, and we might plausibly hit one of
649 them, we don't want to actually continue the inferior -- we just
650 want to report the stop. In this case, we just pretend to
651 continue. See the comment by the definition of "pending_stops"
652 for details on why this is needed. */
653 for (const auto &item
: pending_stops
)
655 if (desired_stop_thread_id
== -1
656 || desired_stop_thread_id
== item
.thread_id
)
658 DEBUG_EVENTS ("pending stop anticipated, desired=0x%x, item=0x%x",
659 desired_stop_thread_id
, item
.thread_id
);
667 /* See nat/windows-nat.h. */
669 std::optional
<pending_stop
>
670 windows_process_info::fetch_pending_stop (bool debug_events
)
672 std::optional
<pending_stop
> result
;
673 for (auto iter
= pending_stops
.begin ();
674 iter
!= pending_stops
.end ();
677 if (desired_stop_thread_id
== -1
678 || desired_stop_thread_id
== iter
->thread_id
)
681 current_event
= iter
->event
;
683 DEBUG_EVENTS ("pending stop found in 0x%x (desired=0x%x)",
684 iter
->thread_id
, desired_stop_thread_id
);
686 pending_stops
.erase (iter
);
694 /* See nat/windows-nat.h. */
697 continue_last_debug_event (DWORD continue_status
, bool debug_events
)
699 DEBUG_EVENTS ("ContinueDebugEvent (cpid=%d, ctid=0x%x, %s)",
700 (unsigned) last_wait_event
.dwProcessId
,
701 (unsigned) last_wait_event
.dwThreadId
,
702 continue_status
== DBG_CONTINUE
?
703 "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED");
705 return ContinueDebugEvent (last_wait_event
.dwProcessId
,
706 last_wait_event
.dwThreadId
,
710 /* See nat/windows-nat.h. */
713 wait_for_debug_event (DEBUG_EVENT
*event
, DWORD timeout
)
715 BOOL result
= WaitForDebugEvent (event
, timeout
);
717 last_wait_event
= *event
;
721 /* Flags to pass to UpdateProcThreadAttribute. */
722 #define relocate_aslr_flags ((0x2 << 8) | (0x2 << 16))
724 /* Attribute to pass to UpdateProcThreadAttribute. */
725 #define mitigation_policy 0x00020007
727 /* Pick one of the symbols as a sentinel. */
728 #ifdef PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_OFF
730 static_assert ((PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_OFF
731 | PROCESS_CREATION_MITIGATION_POLICY_BOTTOM_UP_ASLR_ALWAYS_OFF
)
732 == relocate_aslr_flags
,
733 "check that ASLR flag values are correct");
735 static_assert (PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY
== mitigation_policy
,
736 "check that mitigation policy value is correct");
740 /* Helper template for the CreateProcess wrappers.
742 FUNC is the type of the underlying CreateProcess call. CHAR is the
743 character type to use, and INFO is the "startupinfo" type to use.
745 DO_CREATE_PROCESS is the underlying CreateProcess function to use;
746 the remaining arguments are passed to it. */
747 template<typename FUNC
, typename CHAR
, typename INFO
>
749 create_process_wrapper (FUNC
*do_create_process
, const CHAR
*image
,
750 CHAR
*command_line
, DWORD flags
,
751 void *environment
, const CHAR
*cur_dir
,
752 bool no_randomization
,
754 PROCESS_INFORMATION
*process_info
)
756 if (no_randomization
&& disable_randomization_available ())
758 static bool tried_and_failed
;
760 if (!tried_and_failed
)
762 /* Windows 8 is required for the real declaration, but to
763 allow building on earlier versions of Windows, we declare
765 struct gdb_extended_info
768 gdb_lpproc_thread_attribute_list lpAttributeList
;
771 # ifndef EXTENDED_STARTUPINFO_PRESENT
772 # define EXTENDED_STARTUPINFO_PRESENT 0x00080000
775 gdb_extended_info info_ex
{};
777 if (startup_info
!= nullptr)
778 info_ex
.StartupInfo
= *startup_info
;
779 info_ex
.StartupInfo
.cb
= sizeof (info_ex
);
781 /* Ignore the result here. The documentation says the first
782 call always fails, by design. */
783 InitializeProcThreadAttributeList (nullptr, 1, 0, &size
);
784 info_ex
.lpAttributeList
785 = (gdb_lpproc_thread_attribute_list
) alloca (size
);
786 InitializeProcThreadAttributeList (info_ex
.lpAttributeList
,
789 std::optional
<BOOL
> return_value
;
790 DWORD attr_flags
= relocate_aslr_flags
;
791 if (!UpdateProcThreadAttribute (info_ex
.lpAttributeList
, 0,
796 tried_and_failed
= true;
799 BOOL result
= do_create_process (image
, command_line
,
803 | EXTENDED_STARTUPINFO_PRESENT
),
806 &info_ex
.StartupInfo
,
809 return_value
= result
;
810 else if (GetLastError () == ERROR_INVALID_PARAMETER
)
811 tried_and_failed
= true;
813 return_value
= FALSE
;
816 DeleteProcThreadAttributeList (info_ex
.lpAttributeList
);
818 if (return_value
.has_value ())
819 return *return_value
;
823 return do_create_process (image
,
824 command_line
, /* command line */
825 nullptr, /* Security */
826 nullptr, /* thread */
827 TRUE
, /* inherit handles */
828 flags
, /* start flags */
829 environment
, /* environment */
830 cur_dir
, /* current directory */
835 /* See nat/windows-nat.h. */
838 create_process (const char *image
, char *command_line
, DWORD flags
,
839 void *environment
, const char *cur_dir
,
840 bool no_randomization
,
841 STARTUPINFOA
*startup_info
,
842 PROCESS_INFORMATION
*process_info
)
844 return create_process_wrapper (CreateProcessA
, image
, command_line
, flags
,
845 environment
, cur_dir
, no_randomization
,
846 startup_info
, process_info
);
851 /* See nat/windows-nat.h. */
854 create_process (const wchar_t *image
, wchar_t *command_line
, DWORD flags
,
855 void *environment
, const wchar_t *cur_dir
,
856 bool no_randomization
,
857 STARTUPINFOW
*startup_info
,
858 PROCESS_INFORMATION
*process_info
)
860 return create_process_wrapper (CreateProcessW
, image
, command_line
, flags
,
861 environment
, cur_dir
, no_randomization
,
862 startup_info
, process_info
);
865 #endif /* __CYGWIN__ */
867 /* Define dummy functions which always return error for the rare cases where
868 these functions could not be found. */
869 template<typename
... T
>
876 template<typename
... T
>
884 bad_GetCurrentConsoleFont (HANDLE w
, BOOL bMaxWindow
, CONSOLE_FONT_INFO
*f
)
891 bad_GetConsoleFontSize (HANDLE w
, DWORD nFont
)
899 /* See windows-nat.h. */
902 disable_randomization_available ()
904 return (InitializeProcThreadAttributeList
!= nullptr
905 && UpdateProcThreadAttribute
!= nullptr
906 && DeleteProcThreadAttributeList
!= nullptr);
909 /* See windows-nat.h. */
912 initialize_loadable ()
917 #define GPA(m, func) \
918 func = (func ## _ftype *) GetProcAddress (m, #func)
920 hm
= LoadLibrary (TEXT ("kernel32.dll"));
923 GPA (hm
, DebugActiveProcessStop
);
924 GPA (hm
, DebugBreakProcess
);
925 GPA (hm
, DebugSetProcessKillOnExit
);
926 GPA (hm
, GetConsoleFontSize
);
927 GPA (hm
, DebugActiveProcessStop
);
928 GPA (hm
, GetCurrentConsoleFont
);
930 GPA (hm
, Wow64SuspendThread
);
931 GPA (hm
, Wow64GetThreadContext
);
932 GPA (hm
, Wow64SetThreadContext
);
933 GPA (hm
, Wow64GetThreadSelectorEntry
);
935 GPA (hm
, GenerateConsoleCtrlEvent
);
936 GPA (hm
, GetThreadDescription
);
938 GPA (hm
, InitializeProcThreadAttributeList
);
939 GPA (hm
, UpdateProcThreadAttribute
);
940 GPA (hm
, DeleteProcThreadAttributeList
);
943 /* Set variables to dummy versions of these processes if the function
944 wasn't found in kernel32.dll. */
945 if (!DebugBreakProcess
)
946 DebugBreakProcess
= bad
;
947 if (!DebugActiveProcessStop
|| !DebugSetProcessKillOnExit
)
949 DebugActiveProcessStop
= bad
;
950 DebugSetProcessKillOnExit
= bad
;
952 if (!GetConsoleFontSize
)
953 GetConsoleFontSize
= bad_GetConsoleFontSize
;
954 if (!GetCurrentConsoleFont
)
955 GetCurrentConsoleFont
= bad_GetCurrentConsoleFont
;
957 /* Load optional functions used for retrieving filename information
958 associated with the currently debugged process or its dlls. */
959 hm
= LoadLibrary (TEXT ("psapi.dll"));
962 GPA (hm
, EnumProcessModules
);
964 GPA (hm
, EnumProcessModulesEx
);
966 GPA (hm
, GetModuleInformation
);
967 GPA (hm
, GetModuleFileNameExA
);
968 GPA (hm
, GetModuleFileNameExW
);
971 if (!EnumProcessModules
|| !GetModuleInformation
972 || !GetModuleFileNameExA
|| !GetModuleFileNameExW
)
974 /* Set variables to dummy versions of these processes if the function
975 wasn't found in psapi.dll. */
976 EnumProcessModules
= bad
;
977 GetModuleInformation
= bad
;
978 GetModuleFileNameExA
= bad
;
979 GetModuleFileNameExW
= bad
;
984 hm
= LoadLibrary (TEXT ("advapi32.dll"));
987 GPA (hm
, OpenProcessToken
);
988 GPA (hm
, LookupPrivilegeValueA
);
989 GPA (hm
, AdjustTokenPrivileges
);
990 /* Only need to set one of these since if OpenProcessToken fails nothing
992 if (!OpenProcessToken
|| !LookupPrivilegeValueA
993 || !AdjustTokenPrivileges
)
994 OpenProcessToken
= bad
;
997 /* On some versions of Windows, this function is only available in
998 KernelBase.dll, not kernel32.dll. */
999 if (GetThreadDescription
== nullptr)
1001 hm
= LoadLibrary (TEXT ("KernelBase.dll"));
1003 GPA (hm
, GetThreadDescription
);