Add `set print repeats' tests for C/C++ arrays
[binutils-gdb.git] / gdb / nat / windows-nat.c
1 /* Internal interfaces for the Windows code
2 Copyright (C) 1995-2022 Free Software Foundation, Inc.
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"
21 #include "gdbsupport/common-debug.h"
22
23 namespace windows_nat
24 {
25
26 HANDLE current_process_handle;
27 DWORD current_process_id;
28 DWORD main_thread_id;
29 enum gdb_signal last_sig = GDB_SIGNAL_0;
30 DEBUG_EVENT current_event;
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. */
37 static DEBUG_EVENT last_wait_event;
38
39 DWORD desired_stop_thread_id = -1;
40 std::vector<pending_stop> pending_stops;
41 EXCEPTION_RECORD siginfo_er;
42
43 #ifdef __x86_64__
44 bool wow64_process = false;
45 bool ignore_first_breakpoint = false;
46 #endif
47
48 AdjustTokenPrivileges_ftype *AdjustTokenPrivileges;
49 DebugActiveProcessStop_ftype *DebugActiveProcessStop;
50 DebugBreakProcess_ftype *DebugBreakProcess;
51 DebugSetProcessKillOnExit_ftype *DebugSetProcessKillOnExit;
52 EnumProcessModules_ftype *EnumProcessModules;
53 #ifdef __x86_64__
54 EnumProcessModulesEx_ftype *EnumProcessModulesEx;
55 #endif
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;
63 #ifdef __x86_64__
64 Wow64SuspendThread_ftype *Wow64SuspendThread;
65 Wow64GetThreadContext_ftype *Wow64GetThreadContext;
66 Wow64SetThreadContext_ftype *Wow64SetThreadContext;
67 Wow64GetThreadSelectorEntry_ftype *Wow64GetThreadSelectorEntry;
68 #endif
69 GenerateConsoleCtrlEvent_ftype *GenerateConsoleCtrlEvent;
70
71 /* Note that 'debug_events' must be locally defined in the relevant
72 functions. */
73 #define DEBUG_EVENTS(fmt, ...) \
74 debug_prefixed_printf_cond (debug_events, "windows events", fmt, \
75 ## __VA_ARGS__)
76
77 windows_thread_info::~windows_thread_info ()
78 {
79 }
80
81 void
82 windows_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
106 void
107 windows_thread_info::resume ()
108 {
109 if (suspended > 0)
110 {
111 stopped_at_software_breakpoint = false;
112
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 }
122
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
129 static const char *
130 get_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
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;
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
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
186 handle_exception_result
187 handle_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
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");
208 ourstatus->set_stopped (GDB_SIGNAL_SEGV);
209 if (handle_access_violation (rec))
210 return HANDLE_EXCEPTION_UNHANDLED;
211 break;
212 case STATUS_STACK_OVERFLOW:
213 DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
214 ourstatus->set_stopped (GDB_SIGNAL_SEGV);
215 break;
216 case STATUS_FLOAT_DENORMAL_OPERAND:
217 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
218 ourstatus->set_stopped (GDB_SIGNAL_FPE);
219 break;
220 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
221 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
222 ourstatus->set_stopped (GDB_SIGNAL_FPE);
223 break;
224 case STATUS_FLOAT_INEXACT_RESULT:
225 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
226 ourstatus->set_stopped (GDB_SIGNAL_FPE);
227 break;
228 case STATUS_FLOAT_INVALID_OPERATION:
229 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
230 ourstatus->set_stopped (GDB_SIGNAL_FPE);
231 break;
232 case STATUS_FLOAT_OVERFLOW:
233 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
234 ourstatus->set_stopped (GDB_SIGNAL_FPE);
235 break;
236 case STATUS_FLOAT_STACK_CHECK:
237 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
238 ourstatus->set_stopped (GDB_SIGNAL_FPE);
239 break;
240 case STATUS_FLOAT_UNDERFLOW:
241 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
242 ourstatus->set_stopped (GDB_SIGNAL_FPE);
243 break;
244 case STATUS_FLOAT_DIVIDE_BY_ZERO:
245 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
246 ourstatus->set_stopped (GDB_SIGNAL_FPE);
247 break;
248 case STATUS_INTEGER_DIVIDE_BY_ZERO:
249 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
250 ourstatus->set_stopped (GDB_SIGNAL_FPE);
251 break;
252 case STATUS_INTEGER_OVERFLOW:
253 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
254 ourstatus->set_stopped (GDB_SIGNAL_FPE);
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. */
264 ourstatus->set_spurious ();
265 ignore_first_breakpoint = false;
266 }
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;
278 ourstatus->set_stopped (GDB_SIGNAL_INT);
279 break;
280 }
281 #endif
282 /* FALLTHROUGH */
283 case STATUS_WX86_BREAKPOINT:
284 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
285 ourstatus->set_stopped (GDB_SIGNAL_TRAP);
286 break;
287 case DBG_CONTROL_C:
288 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
289 ourstatus->set_stopped (GDB_SIGNAL_INT);
290 break;
291 case DBG_CONTROL_BREAK:
292 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
293 ourstatus->set_stopped (GDB_SIGNAL_INT);
294 break;
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);
299 break;
300 case EXCEPTION_ILLEGAL_INSTRUCTION:
301 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
302 ourstatus->set_stopped (GDB_SIGNAL_ILL);
303 break;
304 case EXCEPTION_PRIV_INSTRUCTION:
305 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
306 ourstatus->set_stopped (GDB_SIGNAL_ILL);
307 break;
308 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
309 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
310 ourstatus->set_stopped (GDB_SIGNAL_ILL);
311 break;
312 case MS_VC_EXCEPTION:
313 DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION");
314 if (handle_ms_vc_exception (rec))
315 {
316 ourstatus->set_stopped (GDB_SIGNAL_TRAP);
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));
330 ourstatus->set_stopped (GDB_SIGNAL_UNKNOWN);
331 break;
332 }
333
334 if (ourstatus->kind () == TARGET_WAITKIND_STOPPED)
335 last_sig = ourstatus->sig ();
336
337 return result;
338
339 #undef DEBUG_EXCEPTION_SIMPLE
340 }
341
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
349 static void
350 windows_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
472 void
473 dll_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
498 void
499 windows_add_all_dlls ()
500 {
501 windows_add_dll (nullptr);
502 }
503
504 /* See nat/windows-nat.h. */
505
506 bool
507 matching_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 {
519 DEBUG_EVENTS ("pending stop anticipated, desired=0x%x, item=0x%x",
520 desired_stop_thread_id, item.thread_id);
521 return true;
522 }
523 }
524
525 return false;
526 }
527
528 /* See nat/windows-nat.h. */
529
530 gdb::optional<pending_stop>
531 fetch_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
544 DEBUG_EVENTS ("pending stop found in 0x%x (desired=0x%x)",
545 iter->thread_id, desired_stop_thread_id);
546
547 pending_stops.erase (iter);
548 break;
549 }
550 }
551
552 return result;
553 }
554
555 /* See nat/windows-nat.h. */
556
557 BOOL
558 continue_last_debug_event (DWORD continue_status, bool debug_events)
559 {
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");
565
566 return ContinueDebugEvent (last_wait_event.dwProcessId,
567 last_wait_event.dwThreadId,
568 continue_status);
569 }
570
571 /* See nat/windows-nat.h. */
572
573 BOOL
574 wait_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 }
581
582 /* Define dummy functions which always return error for the rare cases where
583 these functions could not be found. */
584 template<typename... T>
585 BOOL WINAPI
586 bad (T... args)
587 {
588 return FALSE;
589 }
590
591 template<typename... T>
592 DWORD WINAPI
593 bad (T... args)
594 {
595 return 0;
596 }
597
598 static BOOL WINAPI
599 bad_GetCurrentConsoleFont (HANDLE w, BOOL bMaxWindow, CONSOLE_FONT_INFO *f)
600 {
601 f->nFont = 0;
602 return 1;
603 }
604
605 static COORD WINAPI
606 bad_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
616 bool
617 initialize_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
640 GPA (hm, GenerateConsoleCtrlEvent);
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
702 }