1 /* Internal interfaces for the Windows code
2 Copyright (C) 1995-2021 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 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
202 /* Record the context of the current thread. */
203 thread_rec (ptid_t (current_event
.dwProcessId
, current_event
.dwThreadId
, 0),
208 case EXCEPTION_ACCESS_VIOLATION
:
209 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
210 ourstatus
->value
.sig
= GDB_SIGNAL_SEGV
;
211 if (handle_access_violation (rec
))
212 return HANDLE_EXCEPTION_UNHANDLED
;
214 case STATUS_STACK_OVERFLOW
:
215 DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
216 ourstatus
->value
.sig
= GDB_SIGNAL_SEGV
;
218 case STATUS_FLOAT_DENORMAL_OPERAND
:
219 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
220 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
222 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
223 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
224 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
226 case STATUS_FLOAT_INEXACT_RESULT
:
227 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
228 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
230 case STATUS_FLOAT_INVALID_OPERATION
:
231 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
232 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
234 case STATUS_FLOAT_OVERFLOW
:
235 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
236 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
238 case STATUS_FLOAT_STACK_CHECK
:
239 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
240 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
242 case STATUS_FLOAT_UNDERFLOW
:
243 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
244 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
246 case STATUS_FLOAT_DIVIDE_BY_ZERO
:
247 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
248 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
250 case STATUS_INTEGER_DIVIDE_BY_ZERO
:
251 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
252 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
254 case STATUS_INTEGER_OVERFLOW
:
255 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
256 ourstatus
->value
.sig
= GDB_SIGNAL_FPE
;
258 case EXCEPTION_BREAKPOINT
:
260 if (ignore_first_breakpoint
)
262 /* For WOW64 processes, there are always 2 breakpoint exceptions
263 on startup, first a BREAKPOINT for the 64bit ntdll.dll,
264 then a WX86_BREAKPOINT for the 32bit ntdll.dll.
265 Here we only care about the WX86_BREAKPOINT's. */
266 ourstatus
->kind
= TARGET_WAITKIND_SPURIOUS
;
267 ignore_first_breakpoint
= false;
269 else if (wow64_process
)
271 /* This breakpoint exception is triggered for WOW64 processes when
272 reaching an int3 instruction in 64bit code.
273 gdb checks for int3 in case of SIGTRAP, this fails because
274 Wow64GetThreadContext can only report the pc of 32bit code, and
275 gdb lets the target process continue.
276 So handle it as SIGINT instead, then the target is stopped
278 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
279 rec
->ExceptionCode
= DBG_CONTROL_C
;
280 ourstatus
->value
.sig
= GDB_SIGNAL_INT
;
285 case STATUS_WX86_BREAKPOINT
:
286 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
287 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
290 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
291 ourstatus
->value
.sig
= GDB_SIGNAL_INT
;
293 case DBG_CONTROL_BREAK
:
294 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
295 ourstatus
->value
.sig
= GDB_SIGNAL_INT
;
297 case EXCEPTION_SINGLE_STEP
:
298 case STATUS_WX86_SINGLE_STEP
:
299 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
300 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
302 case EXCEPTION_ILLEGAL_INSTRUCTION
:
303 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
304 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
306 case EXCEPTION_PRIV_INSTRUCTION
:
307 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
308 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
310 case EXCEPTION_NONCONTINUABLE_EXCEPTION
:
311 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
312 ourstatus
->value
.sig
= GDB_SIGNAL_ILL
;
314 case MS_VC_EXCEPTION
:
315 DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION");
316 if (handle_ms_vc_exception (rec
))
318 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
319 result
= HANDLE_EXCEPTION_IGNORED
;
322 /* treat improperly formed exception as unknown */
325 /* Treat unhandled first chance exceptions specially. */
326 if (current_event
.u
.Exception
.dwFirstChance
)
327 return HANDLE_EXCEPTION_UNHANDLED
;
328 debug_printf ("gdb: unknown target exception 0x%08x at %s\n",
329 (unsigned) current_event
.u
.Exception
.ExceptionRecord
.ExceptionCode
,
330 host_address_to_string (
331 current_event
.u
.Exception
.ExceptionRecord
.ExceptionAddress
));
332 ourstatus
->value
.sig
= GDB_SIGNAL_UNKNOWN
;
336 last_sig
= ourstatus
->value
.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
;