Share DLL code between gdb and gdbserver
[deliverable/binutils-gdb.git] / gdb / nat / windows-nat.c
1 /* Internal interfaces for the Windows code
2 Copyright (C) 1995-2021 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 const char *
124 get_image_name (HANDLE h, void *address, int unicode)
125 {
126 #ifdef __CYGWIN__
127 static char buf[MAX_PATH];
128 #else
129 static char buf[(2 * MAX_PATH) + 1];
130 #endif
131 DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
132 char *address_ptr;
133 int len = 0;
134 char b[2];
135 SIZE_T done;
136
137 /* Attempt to read the name of the dll that was detected.
138 This is documented to work only when actively debugging
139 a program. It will not work for attached processes. */
140 if (address == NULL)
141 return NULL;
142
143 /* See if we could read the address of a string, and that the
144 address isn't null. */
145 if (!ReadProcessMemory (h, address, &address_ptr,
146 sizeof (address_ptr), &done)
147 || done != sizeof (address_ptr)
148 || !address_ptr)
149 return NULL;
150
151 /* Find the length of the string. */
152 while (ReadProcessMemory (h, address_ptr + len++ * size, &b, size, &done)
153 && (b[0] != 0 || b[size - 1] != 0) && done == size)
154 continue;
155
156 if (!unicode)
157 ReadProcessMemory (h, address_ptr, buf, len, &done);
158 else
159 {
160 WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR));
161 ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
162 &done);
163 #ifdef __CYGWIN__
164 wcstombs (buf, unicode_address, MAX_PATH);
165 #else
166 WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, sizeof buf,
167 0, 0);
168 #endif
169 }
170
171 return buf;
172 }
173
174 /* The exception thrown by a program to tell the debugger the name of
175 a thread. The exception record contains an ID of a thread and a
176 name to give it. This exception has no documented name, but MSDN
177 dubs it "MS_VC_EXCEPTION" in one code example. */
178 #define MS_VC_EXCEPTION 0x406d1388
179
180 handle_exception_result
181 handle_exception (struct target_waitstatus *ourstatus, bool debug_exceptions)
182 {
183 #define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \
184 debug_printf ("gdb: Target exception %s at %s\n", x, \
185 host_address_to_string (\
186 current_event.u.Exception.ExceptionRecord.ExceptionAddress))
187
188 EXCEPTION_RECORD *rec = &current_event.u.Exception.ExceptionRecord;
189 DWORD code = rec->ExceptionCode;
190 handle_exception_result result = HANDLE_EXCEPTION_HANDLED;
191
192 memcpy (&siginfo_er, rec, sizeof siginfo_er);
193
194 ourstatus->kind = TARGET_WAITKIND_STOPPED;
195
196 /* Record the context of the current thread. */
197 thread_rec (ptid_t (current_event.dwProcessId, current_event.dwThreadId, 0),
198 DONT_SUSPEND);
199
200 switch (code)
201 {
202 case EXCEPTION_ACCESS_VIOLATION:
203 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
204 ourstatus->value.sig = GDB_SIGNAL_SEGV;
205 if (handle_access_violation (rec))
206 return HANDLE_EXCEPTION_UNHANDLED;
207 break;
208 case STATUS_STACK_OVERFLOW:
209 DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
210 ourstatus->value.sig = GDB_SIGNAL_SEGV;
211 break;
212 case STATUS_FLOAT_DENORMAL_OPERAND:
213 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
214 ourstatus->value.sig = GDB_SIGNAL_FPE;
215 break;
216 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
217 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
218 ourstatus->value.sig = GDB_SIGNAL_FPE;
219 break;
220 case STATUS_FLOAT_INEXACT_RESULT:
221 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INEXACT_RESULT");
222 ourstatus->value.sig = GDB_SIGNAL_FPE;
223 break;
224 case STATUS_FLOAT_INVALID_OPERATION:
225 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_INVALID_OPERATION");
226 ourstatus->value.sig = GDB_SIGNAL_FPE;
227 break;
228 case STATUS_FLOAT_OVERFLOW:
229 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_OVERFLOW");
230 ourstatus->value.sig = GDB_SIGNAL_FPE;
231 break;
232 case STATUS_FLOAT_STACK_CHECK:
233 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_STACK_CHECK");
234 ourstatus->value.sig = GDB_SIGNAL_FPE;
235 break;
236 case STATUS_FLOAT_UNDERFLOW:
237 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_UNDERFLOW");
238 ourstatus->value.sig = GDB_SIGNAL_FPE;
239 break;
240 case STATUS_FLOAT_DIVIDE_BY_ZERO:
241 DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DIVIDE_BY_ZERO");
242 ourstatus->value.sig = GDB_SIGNAL_FPE;
243 break;
244 case STATUS_INTEGER_DIVIDE_BY_ZERO:
245 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_DIVIDE_BY_ZERO");
246 ourstatus->value.sig = GDB_SIGNAL_FPE;
247 break;
248 case STATUS_INTEGER_OVERFLOW:
249 DEBUG_EXCEPTION_SIMPLE ("STATUS_INTEGER_OVERFLOW");
250 ourstatus->value.sig = GDB_SIGNAL_FPE;
251 break;
252 case EXCEPTION_BREAKPOINT:
253 #ifdef __x86_64__
254 if (ignore_first_breakpoint)
255 {
256 /* For WOW64 processes, there are always 2 breakpoint exceptions
257 on startup, first a BREAKPOINT for the 64bit ntdll.dll,
258 then a WX86_BREAKPOINT for the 32bit ntdll.dll.
259 Here we only care about the WX86_BREAKPOINT's. */
260 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
261 ignore_first_breakpoint = false;
262 }
263 else if (wow64_process)
264 {
265 /* This breakpoint exception is triggered for WOW64 processes when
266 reaching an int3 instruction in 64bit code.
267 gdb checks for int3 in case of SIGTRAP, this fails because
268 Wow64GetThreadContext can only report the pc of 32bit code, and
269 gdb lets the target process continue.
270 So handle it as SIGINT instead, then the target is stopped
271 unconditionally. */
272 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
273 rec->ExceptionCode = DBG_CONTROL_C;
274 ourstatus->value.sig = GDB_SIGNAL_INT;
275 break;
276 }
277 #endif
278 /* FALLTHROUGH */
279 case STATUS_WX86_BREAKPOINT:
280 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_BREAKPOINT");
281 ourstatus->value.sig = GDB_SIGNAL_TRAP;
282 break;
283 case DBG_CONTROL_C:
284 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_C");
285 ourstatus->value.sig = GDB_SIGNAL_INT;
286 break;
287 case DBG_CONTROL_BREAK:
288 DEBUG_EXCEPTION_SIMPLE ("DBG_CONTROL_BREAK");
289 ourstatus->value.sig = GDB_SIGNAL_INT;
290 break;
291 case EXCEPTION_SINGLE_STEP:
292 case STATUS_WX86_SINGLE_STEP:
293 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_SINGLE_STEP");
294 ourstatus->value.sig = GDB_SIGNAL_TRAP;
295 break;
296 case EXCEPTION_ILLEGAL_INSTRUCTION:
297 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ILLEGAL_INSTRUCTION");
298 ourstatus->value.sig = GDB_SIGNAL_ILL;
299 break;
300 case EXCEPTION_PRIV_INSTRUCTION:
301 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_PRIV_INSTRUCTION");
302 ourstatus->value.sig = GDB_SIGNAL_ILL;
303 break;
304 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
305 DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_NONCONTINUABLE_EXCEPTION");
306 ourstatus->value.sig = GDB_SIGNAL_ILL;
307 break;
308 case MS_VC_EXCEPTION:
309 DEBUG_EXCEPTION_SIMPLE ("MS_VC_EXCEPTION");
310 if (handle_ms_vc_exception (rec))
311 {
312 ourstatus->value.sig = GDB_SIGNAL_TRAP;
313 result = HANDLE_EXCEPTION_IGNORED;
314 break;
315 }
316 /* treat improperly formed exception as unknown */
317 /* FALLTHROUGH */
318 default:
319 /* Treat unhandled first chance exceptions specially. */
320 if (current_event.u.Exception.dwFirstChance)
321 return HANDLE_EXCEPTION_UNHANDLED;
322 debug_printf ("gdb: unknown target exception 0x%08x at %s\n",
323 (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionCode,
324 host_address_to_string (
325 current_event.u.Exception.ExceptionRecord.ExceptionAddress));
326 ourstatus->value.sig = GDB_SIGNAL_UNKNOWN;
327 break;
328 }
329
330 last_sig = ourstatus->value.sig;
331 return result;
332
333 #undef DEBUG_EXCEPTION_SIMPLE
334 }
335
336 /* Iterate over all DLLs currently mapped by our inferior, looking for
337 a DLL which is loaded at LOAD_ADDR. If found, add the DLL to our
338 list of solibs; otherwise do nothing. LOAD_ADDR NULL means add all
339 DLLs to the list of solibs; this is used when the inferior finishes
340 its initialization, and all the DLLs it statically depends on are
341 presumed loaded. */
342
343 static void
344 windows_add_dll (LPVOID load_addr)
345 {
346 HMODULE dummy_hmodule;
347 DWORD cb_needed;
348 HMODULE *hmodules;
349 int i;
350
351 #ifdef __x86_64__
352 if (wow64_process)
353 {
354 if (EnumProcessModulesEx (current_process_handle, &dummy_hmodule,
355 sizeof (HMODULE), &cb_needed,
356 LIST_MODULES_32BIT) == 0)
357 return;
358 }
359 else
360 #endif
361 {
362 if (EnumProcessModules (current_process_handle, &dummy_hmodule,
363 sizeof (HMODULE), &cb_needed) == 0)
364 return;
365 }
366
367 if (cb_needed < 1)
368 return;
369
370 hmodules = (HMODULE *) alloca (cb_needed);
371 #ifdef __x86_64__
372 if (wow64_process)
373 {
374 if (EnumProcessModulesEx (current_process_handle, hmodules,
375 cb_needed, &cb_needed,
376 LIST_MODULES_32BIT) == 0)
377 return;
378 }
379 else
380 #endif
381 {
382 if (EnumProcessModules (current_process_handle, hmodules,
383 cb_needed, &cb_needed) == 0)
384 return;
385 }
386
387 char system_dir[MAX_PATH];
388 char syswow_dir[MAX_PATH];
389 size_t system_dir_len = 0;
390 bool convert_syswow_dir = false;
391 #ifdef __x86_64__
392 if (wow64_process)
393 #endif
394 {
395 /* This fails on 32bit Windows because it has no SysWOW64 directory,
396 and in this case a path conversion isn't necessary. */
397 UINT len = GetSystemWow64DirectoryA (syswow_dir, sizeof (syswow_dir));
398 if (len > 0)
399 {
400 /* Check that we have passed a large enough buffer. */
401 gdb_assert (len < sizeof (syswow_dir));
402
403 len = GetSystemDirectoryA (system_dir, sizeof (system_dir));
404 /* Error check. */
405 gdb_assert (len != 0);
406 /* Check that we have passed a large enough buffer. */
407 gdb_assert (len < sizeof (system_dir));
408
409 strcat (system_dir, "\\");
410 strcat (syswow_dir, "\\");
411 system_dir_len = strlen (system_dir);
412
413 convert_syswow_dir = true;
414 }
415
416 }
417 for (i = 1; i < (int) (cb_needed / sizeof (HMODULE)); i++)
418 {
419 MODULEINFO mi;
420 #ifdef __USEWIDE
421 wchar_t dll_name[MAX_PATH];
422 char dll_name_mb[MAX_PATH];
423 #else
424 char dll_name[MAX_PATH];
425 #endif
426 const char *name;
427 if (GetModuleInformation (current_process_handle, hmodules[i],
428 &mi, sizeof (mi)) == 0)
429 continue;
430
431 if (GetModuleFileNameEx (current_process_handle, hmodules[i],
432 dll_name, sizeof (dll_name)) == 0)
433 continue;
434 #ifdef __USEWIDE
435 wcstombs (dll_name_mb, dll_name, MAX_PATH);
436 name = dll_name_mb;
437 #else
438 name = dll_name;
439 #endif
440 /* Convert the DLL path of 32bit processes returned by
441 GetModuleFileNameEx from the 64bit system directory to the
442 32bit syswow64 directory if necessary. */
443 std::string syswow_dll_path;
444 if (convert_syswow_dir
445 && strncasecmp (name, system_dir, system_dir_len) == 0
446 && strchr (name + system_dir_len, '\\') == nullptr)
447 {
448 syswow_dll_path = syswow_dir;
449 syswow_dll_path += name + system_dir_len;
450 name = syswow_dll_path.c_str();
451 }
452
453 /* Record the DLL if either LOAD_ADDR is NULL or the address
454 at which the DLL was loaded is equal to LOAD_ADDR. */
455 if (!(load_addr != nullptr && mi.lpBaseOfDll != load_addr))
456 {
457 handle_load_dll (name, mi.lpBaseOfDll);
458 if (load_addr != nullptr)
459 return;
460 }
461 }
462 }
463
464 /* See nat/windows-nat.h. */
465
466 void
467 dll_loaded_event ()
468 {
469 gdb_assert (current_event.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT);
470
471 LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
472 const char *dll_name;
473
474 /* Try getting the DLL name via the lpImageName field of the event.
475 Note that Microsoft documents this fields as strictly optional,
476 in the sense that it might be NULL. And the first DLL event in
477 particular is explicitly documented as "likely not pass[ed]"
478 (source: MSDN LOAD_DLL_DEBUG_INFO structure). */
479 dll_name = get_image_name (current_process_handle,
480 event->lpImageName, event->fUnicode);
481 /* If the DLL name could not be gleaned via lpImageName, try harder
482 by enumerating all the DLLs loaded into the inferior, looking for
483 one that is loaded at base address = lpBaseOfDll. */
484 if (dll_name != nullptr)
485 handle_load_dll (dll_name, event->lpBaseOfDll);
486 else if (event->lpBaseOfDll != nullptr)
487 windows_add_dll (event->lpBaseOfDll);
488 }
489
490 /* See nat/windows-nat.h. */
491
492 void
493 windows_add_all_dlls ()
494 {
495 windows_add_dll (nullptr);
496 }
497
498 /* See nat/windows-nat.h. */
499
500 bool
501 matching_pending_stop (bool debug_events)
502 {
503 /* If there are pending stops, and we might plausibly hit one of
504 them, we don't want to actually continue the inferior -- we just
505 want to report the stop. In this case, we just pretend to
506 continue. See the comment by the definition of "pending_stops"
507 for details on why this is needed. */
508 for (const auto &item : pending_stops)
509 {
510 if (desired_stop_thread_id == -1
511 || desired_stop_thread_id == item.thread_id)
512 {
513 DEBUG_EVENTS ("pending stop anticipated, desired=0x%x, item=0x%x",
514 desired_stop_thread_id, item.thread_id);
515 return true;
516 }
517 }
518
519 return false;
520 }
521
522 /* See nat/windows-nat.h. */
523
524 gdb::optional<pending_stop>
525 fetch_pending_stop (bool debug_events)
526 {
527 gdb::optional<pending_stop> result;
528 for (auto iter = pending_stops.begin ();
529 iter != pending_stops.end ();
530 ++iter)
531 {
532 if (desired_stop_thread_id == -1
533 || desired_stop_thread_id == iter->thread_id)
534 {
535 result = *iter;
536 current_event = iter->event;
537
538 DEBUG_EVENTS ("pending stop found in 0x%x (desired=0x%x)",
539 iter->thread_id, desired_stop_thread_id);
540
541 pending_stops.erase (iter);
542 break;
543 }
544 }
545
546 return result;
547 }
548
549 /* See nat/windows-nat.h. */
550
551 BOOL
552 continue_last_debug_event (DWORD continue_status, bool debug_events)
553 {
554 DEBUG_EVENTS ("ContinueDebugEvent (cpid=%d, ctid=0x%x, %s)",
555 (unsigned) last_wait_event.dwProcessId,
556 (unsigned) last_wait_event.dwThreadId,
557 continue_status == DBG_CONTINUE ?
558 "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED");
559
560 return ContinueDebugEvent (last_wait_event.dwProcessId,
561 last_wait_event.dwThreadId,
562 continue_status);
563 }
564
565 /* See nat/windows-nat.h. */
566
567 BOOL
568 wait_for_debug_event (DEBUG_EVENT *event, DWORD timeout)
569 {
570 BOOL result = WaitForDebugEvent (event, timeout);
571 if (result)
572 last_wait_event = *event;
573 return result;
574 }
575
576 /* Define dummy functions which always return error for the rare cases where
577 these functions could not be found. */
578 template<typename... T>
579 BOOL WINAPI
580 bad (T... args)
581 {
582 return FALSE;
583 }
584
585 template<typename... T>
586 DWORD WINAPI
587 bad (T... args)
588 {
589 return 0;
590 }
591
592 static BOOL WINAPI
593 bad_GetCurrentConsoleFont (HANDLE w, BOOL bMaxWindow, CONSOLE_FONT_INFO *f)
594 {
595 f->nFont = 0;
596 return 1;
597 }
598
599 static COORD WINAPI
600 bad_GetConsoleFontSize (HANDLE w, DWORD nFont)
601 {
602 COORD size;
603 size.X = 8;
604 size.Y = 12;
605 return size;
606 }
607
608 /* See windows-nat.h. */
609
610 bool
611 initialize_loadable ()
612 {
613 bool result = true;
614 HMODULE hm = NULL;
615
616 #define GPA(m, func) \
617 func = (func ## _ftype *) GetProcAddress (m, #func)
618
619 hm = LoadLibrary (TEXT ("kernel32.dll"));
620 if (hm)
621 {
622 GPA (hm, DebugActiveProcessStop);
623 GPA (hm, DebugBreakProcess);
624 GPA (hm, DebugSetProcessKillOnExit);
625 GPA (hm, GetConsoleFontSize);
626 GPA (hm, DebugActiveProcessStop);
627 GPA (hm, GetCurrentConsoleFont);
628 #ifdef __x86_64__
629 GPA (hm, Wow64SuspendThread);
630 GPA (hm, Wow64GetThreadContext);
631 GPA (hm, Wow64SetThreadContext);
632 GPA (hm, Wow64GetThreadSelectorEntry);
633 #endif
634 GPA (hm, GenerateConsoleCtrlEvent);
635 }
636
637 /* Set variables to dummy versions of these processes if the function
638 wasn't found in kernel32.dll. */
639 if (!DebugBreakProcess)
640 DebugBreakProcess = bad;
641 if (!DebugActiveProcessStop || !DebugSetProcessKillOnExit)
642 {
643 DebugActiveProcessStop = bad;
644 DebugSetProcessKillOnExit = bad;
645 }
646 if (!GetConsoleFontSize)
647 GetConsoleFontSize = bad_GetConsoleFontSize;
648 if (!GetCurrentConsoleFont)
649 GetCurrentConsoleFont = bad_GetCurrentConsoleFont;
650
651 /* Load optional functions used for retrieving filename information
652 associated with the currently debugged process or its dlls. */
653 hm = LoadLibrary (TEXT ("psapi.dll"));
654 if (hm)
655 {
656 GPA (hm, EnumProcessModules);
657 #ifdef __x86_64__
658 GPA (hm, EnumProcessModulesEx);
659 #endif
660 GPA (hm, GetModuleInformation);
661 GPA (hm, GetModuleFileNameExA);
662 GPA (hm, GetModuleFileNameExW);
663 }
664
665 if (!EnumProcessModules || !GetModuleInformation
666 || !GetModuleFileNameExA || !GetModuleFileNameExW)
667 {
668 /* Set variables to dummy versions of these processes if the function
669 wasn't found in psapi.dll. */
670 EnumProcessModules = bad;
671 GetModuleInformation = bad;
672 GetModuleFileNameExA = bad;
673 GetModuleFileNameExW = bad;
674
675 result = false;
676 }
677
678 hm = LoadLibrary (TEXT ("advapi32.dll"));
679 if (hm)
680 {
681 GPA (hm, OpenProcessToken);
682 GPA (hm, LookupPrivilegeValueA);
683 GPA (hm, AdjustTokenPrivileges);
684 /* Only need to set one of these since if OpenProcessToken fails nothing
685 else is needed. */
686 if (!OpenProcessToken || !LookupPrivilegeValueA
687 || !AdjustTokenPrivileges)
688 OpenProcessToken = bad;
689 }
690
691 #undef GPA
692
693 return result;
694 }
695
696 }
This page took 0.042837 seconds and 4 git commands to generate.