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"
26 HANDLE current_process_handle
;
27 DWORD current_process_id
;
29 enum gdb_signal last_sig
= GDB_SIGNAL_0
;
30 DEBUG_EVENT current_event
;
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. */
37 static DEBUG_EVENT last_wait_event
;
39 DWORD desired_stop_thread_id
= -1;
40 std::vector
<pending_stop
> pending_stops
;
41 EXCEPTION_RECORD siginfo_er
;
44 bool wow64_process
= false;
45 bool ignore_first_breakpoint
= false;
48 AdjustTokenPrivileges_ftype
*AdjustTokenPrivileges
;
49 DebugActiveProcessStop_ftype
*DebugActiveProcessStop
;
50 DebugBreakProcess_ftype
*DebugBreakProcess
;
51 DebugSetProcessKillOnExit_ftype
*DebugSetProcessKillOnExit
;
52 EnumProcessModules_ftype
*EnumProcessModules
;
54 EnumProcessModulesEx_ftype
*EnumProcessModulesEx
;
56 GetModuleInformation_ftype
*GetModuleInformation
;
57 GetModuleFileNameExA_ftype
*GetModuleFileNameExA
;
58 GetModuleFileNameExW_ftype
*GetModuleFileNameExW
;
59 LookupPrivilegeValueA_ftype
*LookupPrivilegeValueA
;
60 OpenProcessToken_ftype
*OpenProcessToken
;
61 GetCurrentConsoleFont_ftype
*GetCurrentConsoleFont
;
62 GetConsoleFontSize_ftype
*GetConsoleFontSize
;
64 Wow64SuspendThread_ftype
*Wow64SuspendThread
;
65 Wow64GetThreadContext_ftype
*Wow64GetThreadContext
;
66 Wow64SetThreadContext_ftype
*Wow64SetThreadContext
;
67 Wow64GetThreadSelectorEntry_ftype
*Wow64GetThreadSelectorEntry
;
69 GenerateConsoleCtrlEvent_ftype
*GenerateConsoleCtrlEvent
;
71 /* Note that 'debug_events' must be locally defined in the relevant
73 #define DEBUG_EVENTS(fmt, ...) \
74 debug_prefixed_printf_cond (debug_events, "windows events", fmt, \
77 windows_thread_info::~windows_thread_info ()
82 windows_thread_info::suspend ()
87 if (SuspendThread (h
) == (DWORD
) -1)
89 DWORD err
= GetLastError ();
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
95 We can get Invalid Handle (6) if the main thread
97 if (err
!= ERROR_INVALID_HANDLE
&& err
!= ERROR_ACCESS_DENIED
)
98 warning (_("SuspendThread (tid=0x%x) failed. (winerr %u)"),
99 (unsigned) tid
, (unsigned) err
);
107 windows_thread_info::resume ()
111 stopped_at_software_breakpoint
= false;
113 if (ResumeThread (h
) == (DWORD
) -1)
115 DWORD err
= GetLastError ();
116 warning (_("warning: ResumeThread (tid=0x%x) failed. (winerr %u)"),
117 (unsigned) tid
, (unsigned) err
);
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
130 get_image_name (HANDLE h
, void *address
, int unicode
)
133 static char buf
[MAX_PATH
];
135 static char buf
[(2 * MAX_PATH
) + 1];
137 DWORD size
= unicode
? sizeof (WCHAR
) : sizeof (char);
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. */
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
)
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
)
163 ReadProcessMemory (h
, address_ptr
, buf
, len
, &done
);
166 WCHAR
*unicode_address
= (WCHAR
*) alloca (len
* sizeof (WCHAR
));
167 ReadProcessMemory (h
, address_ptr
, unicode_address
, len
* sizeof (WCHAR
),
170 wcstombs (buf
, unicode_address
, MAX_PATH
);
172 WideCharToMultiByte (CP_ACP
, 0, unicode_address
, len
, buf
, sizeof buf
,
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
186 handle_exception_result
187 handle_exception (struct target_waitstatus
*ourstatus
, bool debug_exceptions
)
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))
194 EXCEPTION_RECORD
*rec
= ¤t_event
.u
.Exception
.ExceptionRecord
;
195 DWORD code
= rec
->ExceptionCode
;
196 handle_exception_result result
= HANDLE_EXCEPTION_HANDLED
;
198 memcpy (&siginfo_er
, rec
, sizeof siginfo_er
);
200 /* Record the context of the current thread. */
201 thread_rec (ptid_t (current_event
.dwProcessId
, current_event
.dwThreadId
, 0),
206 case EXCEPTION_ACCESS_VIOLATION
:
207 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
208 ourstatus
->set_stopped (GDB_SIGNAL_SEGV
);
209 if (handle_access_violation (rec
))
210 return HANDLE_EXCEPTION_UNHANDLED
;
212 case STATUS_STACK_OVERFLOW
:
213 DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
214 ourstatus
->set_stopped (GDB_SIGNAL_SEGV
);
216 case STATUS_FLOAT_DENORMAL_OPERAND
:
217 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
218 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
220 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
221 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
222 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
224 case STATUS_FLOAT_INEXACT_RESULT
:
225 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
226 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
228 case STATUS_FLOAT_INVALID_OPERATION
:
229 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
230 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
232 case STATUS_FLOAT_OVERFLOW
:
233 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
234 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
236 case STATUS_FLOAT_STACK_CHECK
:
237 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
238 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
240 case STATUS_FLOAT_UNDERFLOW
:
241 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
242 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
244 case STATUS_FLOAT_DIVIDE_BY_ZERO
:
245 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
246 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
248 case STATUS_INTEGER_DIVIDE_BY_ZERO
:
249 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
250 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
252 case STATUS_INTEGER_OVERFLOW
:
253 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
254 ourstatus
->set_stopped (GDB_SIGNAL_FPE
);
256 case EXCEPTION_BREAKPOINT
:
258 if (ignore_first_breakpoint
)
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. */
264 ourstatus
->set_spurious ();
265 ignore_first_breakpoint
= false;
267 else if (wow64_process
)
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
276 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
277 rec
->ExceptionCode
= DBG_CONTROL_C
;
278 ourstatus
->set_stopped (GDB_SIGNAL_INT
);
283 case STATUS_WX86_BREAKPOINT
:
284 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
285 ourstatus
->set_stopped (GDB_SIGNAL_TRAP
);
288 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
289 ourstatus
->set_stopped (GDB_SIGNAL_INT
);
291 case DBG_CONTROL_BREAK
:
292 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
293 ourstatus
->set_stopped (GDB_SIGNAL_INT
);
295 case EXCEPTION_SINGLE_STEP
:
296 case STATUS_WX86_SINGLE_STEP
:
297 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
298 ourstatus
->set_stopped (GDB_SIGNAL_TRAP
);
300 case EXCEPTION_ILLEGAL_INSTRUCTION
:
301 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
302 ourstatus
->set_stopped (GDB_SIGNAL_ILL
);
304 case EXCEPTION_PRIV_INSTRUCTION
:
305 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
306 ourstatus
->set_stopped (GDB_SIGNAL_ILL
);
308 case EXCEPTION_NONCONTINUABLE_EXCEPTION
:
309 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
310 ourstatus
->set_stopped (GDB_SIGNAL_ILL
);
312 case MS_VC_EXCEPTION
:
313 DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION");
314 if (handle_ms_vc_exception (rec
))
316 ourstatus
->set_stopped (GDB_SIGNAL_TRAP
);
317 result
= HANDLE_EXCEPTION_IGNORED
;
320 /* treat improperly formed exception as unknown */
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
));
330 ourstatus
->set_stopped (GDB_SIGNAL_UNKNOWN
);
334 if (ourstatus
->kind () == TARGET_WAITKIND_STOPPED
)
335 last_sig
= ourstatus
->sig ();
339 #undef DEBUG_EXCEPTION_SIMPLE
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
350 windows_add_dll (LPVOID load_addr
)
352 HMODULE dummy_hmodule
;
360 if (EnumProcessModulesEx (current_process_handle
, &dummy_hmodule
,
361 sizeof (HMODULE
), &cb_needed
,
362 LIST_MODULES_32BIT
) == 0)
368 if (EnumProcessModules (current_process_handle
, &dummy_hmodule
,
369 sizeof (HMODULE
), &cb_needed
) == 0)
376 hmodules
= (HMODULE
*) alloca (cb_needed
);
380 if (EnumProcessModulesEx (current_process_handle
, hmodules
,
381 cb_needed
, &cb_needed
,
382 LIST_MODULES_32BIT
) == 0)
388 if (EnumProcessModules (current_process_handle
, hmodules
,
389 cb_needed
, &cb_needed
) == 0)
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;
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
));
406 /* Check that we have passed a large enough buffer. */
407 gdb_assert (len
< sizeof (syswow_dir
));
409 len
= GetSystemDirectoryA (system_dir
, sizeof (system_dir
));
411 gdb_assert (len
!= 0);
412 /* Check that we have passed a large enough buffer. */
413 gdb_assert (len
< sizeof (system_dir
));
415 strcat (system_dir
, "\\");
416 strcat (syswow_dir
, "\\");
417 system_dir_len
= strlen (system_dir
);
419 convert_syswow_dir
= true;
423 for (i
= 1; i
< (int) (cb_needed
/ sizeof (HMODULE
)); i
++)
427 wchar_t dll_name
[MAX_PATH
];
428 char dll_name_mb
[MAX_PATH
];
430 char dll_name
[MAX_PATH
];
433 if (GetModuleInformation (current_process_handle
, hmodules
[i
],
434 &mi
, sizeof (mi
)) == 0)
437 if (GetModuleFileNameEx (current_process_handle
, hmodules
[i
],
438 dll_name
, sizeof (dll_name
)) == 0)
441 wcstombs (dll_name_mb
, dll_name
, MAX_PATH
);
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)
454 syswow_dll_path
= syswow_dir
;
455 syswow_dll_path
+= name
+ system_dir_len
;
456 name
= syswow_dll_path
.c_str();
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
))
463 handle_load_dll (name
, mi
.lpBaseOfDll
);
464 if (load_addr
!= nullptr)
470 /* See nat/windows-nat.h. */
475 gdb_assert (current_event
.dwDebugEventCode
== LOAD_DLL_DEBUG_EVENT
);
477 LOAD_DLL_DEBUG_INFO
*event
= ¤t_event
.u
.LoadDll
;
478 const char *dll_name
;
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
);
496 /* See nat/windows-nat.h. */
499 windows_add_all_dlls ()
501 windows_add_dll (nullptr);
504 /* See nat/windows-nat.h. */
507 matching_pending_stop (bool debug_events
)
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
)
516 if (desired_stop_thread_id
== -1
517 || desired_stop_thread_id
== item
.thread_id
)
519 DEBUG_EVENTS ("pending stop anticipated, desired=0x%x, item=0x%x",
520 desired_stop_thread_id
, item
.thread_id
);
528 /* See nat/windows-nat.h. */
530 gdb::optional
<pending_stop
>
531 fetch_pending_stop (bool debug_events
)
533 gdb::optional
<pending_stop
> result
;
534 for (auto iter
= pending_stops
.begin ();
535 iter
!= pending_stops
.end ();
538 if (desired_stop_thread_id
== -1
539 || desired_stop_thread_id
== iter
->thread_id
)
542 current_event
= iter
->event
;
544 DEBUG_EVENTS ("pending stop found in 0x%x (desired=0x%x)",
545 iter
->thread_id
, desired_stop_thread_id
);
547 pending_stops
.erase (iter
);
555 /* See nat/windows-nat.h. */
558 continue_last_debug_event (DWORD continue_status
, bool debug_events
)
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");
566 return ContinueDebugEvent (last_wait_event
.dwProcessId
,
567 last_wait_event
.dwThreadId
,
571 /* See nat/windows-nat.h. */
574 wait_for_debug_event (DEBUG_EVENT
*event
, DWORD timeout
)
576 BOOL result
= WaitForDebugEvent (event
, timeout
);
578 last_wait_event
= *event
;
582 /* Define dummy functions which always return error for the rare cases where
583 these functions could not be found. */
584 template<typename
... T
>
591 template<typename
... T
>
599 bad_GetCurrentConsoleFont (HANDLE w
, BOOL bMaxWindow
, CONSOLE_FONT_INFO
*f
)
606 bad_GetConsoleFontSize (HANDLE w
, DWORD nFont
)
614 /* See windows-nat.h. */
617 initialize_loadable ()
622 #define GPA(m, func) \
623 func = (func ## _ftype *) GetProcAddress (m, #func)
625 hm
= LoadLibrary (TEXT ("kernel32.dll"));
628 GPA (hm
, DebugActiveProcessStop
);
629 GPA (hm
, DebugBreakProcess
);
630 GPA (hm
, DebugSetProcessKillOnExit
);
631 GPA (hm
, GetConsoleFontSize
);
632 GPA (hm
, DebugActiveProcessStop
);
633 GPA (hm
, GetCurrentConsoleFont
);
635 GPA (hm
, Wow64SuspendThread
);
636 GPA (hm
, Wow64GetThreadContext
);
637 GPA (hm
, Wow64SetThreadContext
);
638 GPA (hm
, Wow64GetThreadSelectorEntry
);
640 GPA (hm
, GenerateConsoleCtrlEvent
);
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
)
649 DebugActiveProcessStop
= bad
;
650 DebugSetProcessKillOnExit
= bad
;
652 if (!GetConsoleFontSize
)
653 GetConsoleFontSize
= bad_GetConsoleFontSize
;
654 if (!GetCurrentConsoleFont
)
655 GetCurrentConsoleFont
= bad_GetCurrentConsoleFont
;
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"));
662 GPA (hm
, EnumProcessModules
);
664 GPA (hm
, EnumProcessModulesEx
);
666 GPA (hm
, GetModuleInformation
);
667 GPA (hm
, GetModuleFileNameExA
);
668 GPA (hm
, GetModuleFileNameExW
);
671 if (!EnumProcessModules
|| !GetModuleInformation
672 || !GetModuleFileNameExA
|| !GetModuleFileNameExW
)
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
;
684 hm
= LoadLibrary (TEXT ("advapi32.dll"));
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
692 if (!OpenProcessToken
|| !LookupPrivilegeValueA
693 || !AdjustTokenPrivileges
)
694 OpenProcessToken
= bad
;