5c7946bd33a8462d7f61bd62d838d51398806bea
[deliverable/binutils-gdb.git] / gdbserver / win32-low.cc
1 /* Low level interface to Windows debugging, for gdbserver.
2 Copyright (C) 2006-2021 Free Software Foundation, Inc.
3
4 Contributed by Leo Zayas. Based on "win32-nat.c" from GDB.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21 #include "server.h"
22 #include "regcache.h"
23 #include "gdb/fileio.h"
24 #include "mem-break.h"
25 #include "win32-low.h"
26 #include "gdbthread.h"
27 #include "dll.h"
28 #include "hostio.h"
29 #include <windows.h>
30 #include <winnt.h>
31 #include <imagehlp.h>
32 #include <tlhelp32.h>
33 #include <psapi.h>
34 #include <process.h>
35 #include "gdbsupport/gdb_tilde_expand.h"
36 #include "gdbsupport/common-inferior.h"
37 #include "gdbsupport/gdb_wait.h"
38
39 using namespace windows_nat;
40
41 #ifndef USE_WIN32API
42 #include <sys/cygwin.h>
43 #endif
44
45 #define OUTMSG(X) do { printf X; fflush (stderr); } while (0)
46
47 #define OUTMSG2(X) \
48 do \
49 { \
50 if (debug_threads) \
51 { \
52 printf X; \
53 fflush (stderr); \
54 } \
55 } while (0)
56
57 #ifndef _T
58 #define _T(x) TEXT (x)
59 #endif
60
61 #ifndef COUNTOF
62 #define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0]))
63 #endif
64
65 int using_threads = 1;
66
67 /* Globals. */
68 static int attaching = 0;
69
70 /* A status that hasn't been reported to the core yet, and so
71 win32_wait should return it next, instead of fetching the next
72 debug event off the win32 API. */
73 static struct target_waitstatus cached_status;
74
75 /* Non zero if an interrupt request is to be satisfied by suspending
76 all threads. */
77 static int soft_interrupt_requested = 0;
78
79 /* Non zero if the inferior is stopped in a simulated breakpoint done
80 by suspending all the threads. */
81 static int faked_breakpoint = 0;
82
83 /* True if current_process_handle needs to be closed. */
84 static bool open_process_used = false;
85
86 const struct target_desc *win32_tdesc;
87 #ifdef __x86_64__
88 const struct target_desc *wow64_win32_tdesc;
89 #endif
90
91 #define NUM_REGS (the_low_target.num_regs ())
92
93 /* Get the thread ID from the current selected inferior (the current
94 thread). */
95 static ptid_t
96 current_thread_ptid (void)
97 {
98 return current_ptid;
99 }
100
101 /* The current debug event from WaitForDebugEvent. */
102 static ptid_t
103 debug_event_ptid (DEBUG_EVENT *event)
104 {
105 return ptid_t (event->dwProcessId, event->dwThreadId, 0);
106 }
107
108 /* Get the thread context of the thread associated with TH. */
109
110 static void
111 win32_get_thread_context (windows_thread_info *th)
112 {
113 #ifdef __x86_64__
114 if (wow64_process)
115 memset (&th->wow64_context, 0, sizeof (WOW64_CONTEXT));
116 else
117 #endif
118 memset (&th->context, 0, sizeof (CONTEXT));
119 (*the_low_target.get_thread_context) (th);
120 }
121
122 /* Set the thread context of the thread associated with TH. */
123
124 static void
125 win32_set_thread_context (windows_thread_info *th)
126 {
127 #ifdef __x86_64__
128 if (wow64_process)
129 Wow64SetThreadContext (th->h, &th->wow64_context);
130 else
131 #endif
132 SetThreadContext (th->h, &th->context);
133 }
134
135 /* Set the thread context of the thread associated with TH. */
136
137 static void
138 win32_prepare_to_resume (windows_thread_info *th)
139 {
140 if (the_low_target.prepare_to_resume != NULL)
141 (*the_low_target.prepare_to_resume) (th);
142 }
143
144 /* See win32-low.h. */
145
146 void
147 win32_require_context (windows_thread_info *th)
148 {
149 DWORD context_flags;
150 #ifdef __x86_64__
151 if (wow64_process)
152 context_flags = th->wow64_context.ContextFlags;
153 else
154 #endif
155 context_flags = th->context.ContextFlags;
156 if (context_flags == 0)
157 {
158 th->suspend ();
159 win32_get_thread_context (th);
160 }
161 }
162
163 /* See nat/windows-nat.h. */
164
165 windows_thread_info *
166 windows_nat::thread_rec (ptid_t ptid, thread_disposition_type disposition)
167 {
168 thread_info *thread = find_thread_ptid (ptid);
169 if (thread == NULL)
170 return NULL;
171
172 windows_thread_info *th = (windows_thread_info *) thread_target_data (thread);
173 if (disposition != DONT_INVALIDATE_CONTEXT)
174 win32_require_context (th);
175 return th;
176 }
177
178 /* Add a thread to the thread list. */
179 static windows_thread_info *
180 child_add_thread (DWORD pid, DWORD tid, HANDLE h, void *tlb)
181 {
182 windows_thread_info *th;
183 ptid_t ptid = ptid_t (pid, tid, 0);
184
185 if ((th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT)))
186 return th;
187
188 CORE_ADDR base = (CORE_ADDR) (uintptr_t) tlb;
189 #ifdef __x86_64__
190 /* For WOW64 processes, this is actually the pointer to the 64bit TIB,
191 and the 32bit TIB is exactly 2 pages after it. */
192 if (wow64_process)
193 base += 2 * 4096; /* page size = 4096 */
194 #endif
195 th = new windows_thread_info (tid, h, base);
196
197 add_thread (ptid, th);
198
199 if (the_low_target.thread_added != NULL)
200 (*the_low_target.thread_added) (th);
201
202 return th;
203 }
204
205 /* Delete a thread from the list of threads. */
206 static void
207 delete_thread_info (thread_info *thread)
208 {
209 windows_thread_info *th = (windows_thread_info *) thread_target_data (thread);
210
211 remove_thread (thread);
212 delete th;
213 }
214
215 /* Delete a thread from the list of threads. */
216 static void
217 child_delete_thread (DWORD pid, DWORD tid)
218 {
219 /* If the last thread is exiting, just return. */
220 if (all_threads.size () == 1)
221 return;
222
223 thread_info *thread = find_thread_ptid (ptid_t (pid, tid));
224 if (thread == NULL)
225 return;
226
227 delete_thread_info (thread);
228 }
229
230 /* These watchpoint related wrapper functions simply pass on the function call
231 if the low target has registered a corresponding function. */
232
233 bool
234 win32_process_target::supports_z_point_type (char z_type)
235 {
236 return (z_type == Z_PACKET_SW_BP
237 || (the_low_target.supports_z_point_type != NULL
238 && the_low_target.supports_z_point_type (z_type)));
239 }
240
241 int
242 win32_process_target::insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
243 int size, raw_breakpoint *bp)
244 {
245 if (type == raw_bkpt_type_sw)
246 return insert_memory_breakpoint (bp);
247 else if (the_low_target.insert_point != NULL)
248 return the_low_target.insert_point (type, addr, size, bp);
249 else
250 /* Unsupported (see target.h). */
251 return 1;
252 }
253
254 int
255 win32_process_target::remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
256 int size, raw_breakpoint *bp)
257 {
258 if (type == raw_bkpt_type_sw)
259 return remove_memory_breakpoint (bp);
260 else if (the_low_target.remove_point != NULL)
261 return the_low_target.remove_point (type, addr, size, bp);
262 else
263 /* Unsupported (see target.h). */
264 return 1;
265 }
266
267 bool
268 win32_process_target::stopped_by_watchpoint ()
269 {
270 if (the_low_target.stopped_by_watchpoint != NULL)
271 return the_low_target.stopped_by_watchpoint ();
272 else
273 return false;
274 }
275
276 CORE_ADDR
277 win32_process_target::stopped_data_address ()
278 {
279 if (the_low_target.stopped_data_address != NULL)
280 return the_low_target.stopped_data_address ();
281 else
282 return 0;
283 }
284
285
286 /* Transfer memory from/to the debugged process. */
287 static int
288 child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
289 int write, process_stratum_target *target)
290 {
291 BOOL success;
292 SIZE_T done = 0;
293 DWORD lasterror = 0;
294 uintptr_t addr = (uintptr_t) memaddr;
295
296 if (write)
297 {
298 success = WriteProcessMemory (current_process_handle, (LPVOID) addr,
299 (LPCVOID) our, len, &done);
300 if (!success)
301 lasterror = GetLastError ();
302 FlushInstructionCache (current_process_handle, (LPCVOID) addr, len);
303 }
304 else
305 {
306 success = ReadProcessMemory (current_process_handle, (LPCVOID) addr,
307 (LPVOID) our, len, &done);
308 if (!success)
309 lasterror = GetLastError ();
310 }
311 if (!success && lasterror == ERROR_PARTIAL_COPY && done > 0)
312 return done;
313 else
314 return success ? done : -1;
315 }
316
317 /* Clear out any old thread list and reinitialize it to a pristine
318 state. */
319 static void
320 child_init_thread_list (void)
321 {
322 for_each_thread (delete_thread_info);
323 }
324
325 /* Zero during the child initialization phase, and nonzero otherwise. */
326
327 static int child_initialization_done = 0;
328
329 static void
330 do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
331 {
332 struct process_info *proc;
333
334 last_sig = GDB_SIGNAL_0;
335
336 current_process_handle = proch;
337 current_process_id = pid;
338 main_thread_id = 0;
339
340 soft_interrupt_requested = 0;
341 faked_breakpoint = 0;
342 open_process_used = true;
343
344 memset (&current_event, 0, sizeof (current_event));
345
346 #ifdef __x86_64__
347 BOOL wow64;
348 if (!IsWow64Process (proch, &wow64))
349 {
350 DWORD err = GetLastError ();
351 error ("Check if WOW64 process failed (error %d): %s\n",
352 (int) err, strwinerror (err));
353 }
354 wow64_process = wow64;
355
356 if (wow64_process
357 && (Wow64GetThreadContext == nullptr
358 || Wow64SetThreadContext == nullptr))
359 error ("WOW64 debugging is not supported on this system.\n");
360
361 ignore_first_breakpoint = !attached && wow64_process;
362 #endif
363
364 proc = add_process (pid, attached);
365 #ifdef __x86_64__
366 if (wow64_process)
367 proc->tdesc = wow64_win32_tdesc;
368 else
369 #endif
370 proc->tdesc = win32_tdesc;
371 child_init_thread_list ();
372 child_initialization_done = 0;
373
374 if (the_low_target.initial_stuff != NULL)
375 (*the_low_target.initial_stuff) ();
376
377 cached_status.kind = TARGET_WAITKIND_IGNORE;
378
379 /* Flush all currently pending debug events (thread and dll list) up
380 to the initial breakpoint. */
381 while (1)
382 {
383 struct target_waitstatus status;
384
385 the_target->wait (minus_one_ptid, &status, 0);
386
387 /* Note win32_wait doesn't return thread events. */
388 if (status.kind != TARGET_WAITKIND_LOADED)
389 {
390 cached_status = status;
391 break;
392 }
393
394 {
395 struct thread_resume resume;
396
397 resume.thread = minus_one_ptid;
398 resume.kind = resume_continue;
399 resume.sig = 0;
400
401 the_target->resume (&resume, 1);
402 }
403 }
404
405 /* Now that the inferior has been started and all DLLs have been mapped,
406 we can iterate over all DLLs and load them in.
407
408 We avoid doing it any earlier because, on certain versions of Windows,
409 LOAD_DLL_DEBUG_EVENTs are sometimes not complete. In particular,
410 we have seen on Windows 8.1 that the ntdll.dll load event does not
411 include the DLL name, preventing us from creating an associated SO.
412 A possible explanation is that ntdll.dll might be mapped before
413 the SO info gets created by the Windows system -- ntdll.dll is
414 the first DLL to be reported via LOAD_DLL_DEBUG_EVENT and other DLLs
415 do not seem to suffer from that problem.
416
417 Rather than try to work around this sort of issue, it is much
418 simpler to just ignore DLL load/unload events during the startup
419 phase, and then process them all in one batch now. */
420 windows_add_all_dlls ();
421
422 child_initialization_done = 1;
423 }
424
425 /* Resume all artificially suspended threads if we are continuing
426 execution. */
427 static void
428 continue_one_thread (thread_info *thread, int thread_id)
429 {
430 windows_thread_info *th = (windows_thread_info *) thread_target_data (thread);
431
432 if (thread_id == -1 || thread_id == th->tid)
433 {
434 win32_prepare_to_resume (th);
435
436 if (th->suspended)
437 {
438 DWORD *context_flags;
439 #ifdef __x86_64__
440 if (wow64_process)
441 context_flags = &th->wow64_context.ContextFlags;
442 else
443 #endif
444 context_flags = &th->context.ContextFlags;
445 if (*context_flags)
446 {
447 win32_set_thread_context (th);
448 *context_flags = 0;
449 }
450
451 th->resume ();
452 }
453 }
454 }
455
456 static BOOL
457 child_continue (DWORD continue_status, int thread_id)
458 {
459 desired_stop_thread_id = thread_id;
460 if (matching_pending_stop (debug_threads))
461 return TRUE;
462
463 /* The inferior will only continue after the ContinueDebugEvent
464 call. */
465 for_each_thread ([&] (thread_info *thread)
466 {
467 continue_one_thread (thread, thread_id);
468 });
469 faked_breakpoint = 0;
470
471 return continue_last_debug_event (continue_status, debug_threads);
472 }
473
474 /* Fetch register(s) from the current thread context. */
475 static void
476 child_fetch_inferior_registers (struct regcache *regcache, int r)
477 {
478 int regno;
479 windows_thread_info *th = thread_rec (current_thread_ptid (),
480 INVALIDATE_CONTEXT);
481 if (r == -1 || r > NUM_REGS)
482 child_fetch_inferior_registers (regcache, NUM_REGS);
483 else
484 for (regno = 0; regno < r; regno++)
485 (*the_low_target.fetch_inferior_register) (regcache, th, regno);
486 }
487
488 /* Store a new register value into the current thread context. We don't
489 change the program's context until later, when we resume it. */
490 static void
491 child_store_inferior_registers (struct regcache *regcache, int r)
492 {
493 int regno;
494 windows_thread_info *th = thread_rec (current_thread_ptid (),
495 INVALIDATE_CONTEXT);
496 if (r == -1 || r == 0 || r > NUM_REGS)
497 child_store_inferior_registers (regcache, NUM_REGS);
498 else
499 for (regno = 0; regno < r; regno++)
500 (*the_low_target.store_inferior_register) (regcache, th, regno);
501 }
502
503 /* Map the Windows error number in ERROR to a locale-dependent error
504 message string and return a pointer to it. Typically, the values
505 for ERROR come from GetLastError.
506
507 The string pointed to shall not be modified by the application,
508 but may be overwritten by a subsequent call to strwinerror
509
510 The strwinerror function does not change the current setting
511 of GetLastError. */
512
513 char *
514 strwinerror (DWORD error)
515 {
516 static char buf[1024];
517 TCHAR *msgbuf;
518 DWORD lasterr = GetLastError ();
519 DWORD chars = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
520 | FORMAT_MESSAGE_ALLOCATE_BUFFER,
521 NULL,
522 error,
523 0, /* Default language */
524 (LPTSTR) &msgbuf,
525 0,
526 NULL);
527 if (chars != 0)
528 {
529 /* If there is an \r\n appended, zap it. */
530 if (chars >= 2
531 && msgbuf[chars - 2] == '\r'
532 && msgbuf[chars - 1] == '\n')
533 {
534 chars -= 2;
535 msgbuf[chars] = 0;
536 }
537
538 if (chars > ((COUNTOF (buf)) - 1))
539 {
540 chars = COUNTOF (buf) - 1;
541 msgbuf [chars] = 0;
542 }
543
544 #ifdef UNICODE
545 wcstombs (buf, msgbuf, chars + 1);
546 #else
547 strncpy (buf, msgbuf, chars + 1);
548 #endif
549 LocalFree (msgbuf);
550 }
551 else
552 sprintf (buf, "unknown win32 error (%u)", (unsigned) error);
553
554 SetLastError (lasterr);
555 return buf;
556 }
557
558 static BOOL
559 create_process (const char *program, char *args,
560 DWORD flags, PROCESS_INFORMATION *pi)
561 {
562 const char *inferior_cwd = get_inferior_cwd ();
563 BOOL ret;
564 size_t argslen, proglen;
565
566 proglen = strlen (program) + 1;
567 argslen = strlen (args) + proglen;
568
569 STARTUPINFOA si = { sizeof (STARTUPINFOA) };
570 char *program_and_args = (char *) alloca (argslen + 1);
571
572 strcpy (program_and_args, program);
573 strcat (program_and_args, " ");
574 strcat (program_and_args, args);
575 ret = CreateProcessA (program, /* image name */
576 program_and_args, /* command line */
577 NULL, /* security */
578 NULL, /* thread */
579 TRUE, /* inherit handles */
580 flags, /* start flags */
581 NULL, /* environment */
582 /* current directory */
583 (inferior_cwd == NULL
584 ? NULL
585 : gdb_tilde_expand (inferior_cwd).c_str()),
586 &si, /* start info */
587 pi); /* proc info */
588
589 return ret;
590 }
591
592 /* Start a new process.
593 PROGRAM is the program name.
594 PROGRAM_ARGS is the vector containing the inferior's args.
595 Returns the new PID on success, -1 on failure. Registers the new
596 process with the process list. */
597 int
598 win32_process_target::create_inferior (const char *program,
599 const std::vector<char *> &program_args)
600 {
601 client_state &cs = get_client_state ();
602 #ifndef USE_WIN32API
603 char real_path[PATH_MAX];
604 char *orig_path, *new_path, *path_ptr;
605 #endif
606 BOOL ret;
607 DWORD flags;
608 PROCESS_INFORMATION pi;
609 DWORD err;
610 std::string str_program_args = construct_inferior_arguments (program_args);
611 char *args = (char *) str_program_args.c_str ();
612
613 /* win32_wait needs to know we're not attaching. */
614 attaching = 0;
615
616 if (!program)
617 error ("No executable specified, specify executable to debug.\n");
618
619 flags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
620
621 #ifndef USE_WIN32API
622 orig_path = NULL;
623 path_ptr = getenv ("PATH");
624 if (path_ptr)
625 {
626 int size = cygwin_conv_path_list (CCP_POSIX_TO_WIN_A, path_ptr, NULL, 0);
627 orig_path = (char *) alloca (strlen (path_ptr) + 1);
628 new_path = (char *) alloca (size);
629 strcpy (orig_path, path_ptr);
630 cygwin_conv_path_list (CCP_POSIX_TO_WIN_A, path_ptr, new_path, size);
631 setenv ("PATH", new_path, 1);
632 }
633 cygwin_conv_path (CCP_POSIX_TO_WIN_A, program, real_path, PATH_MAX);
634 program = real_path;
635 #endif
636
637 OUTMSG2 (("Command line is \"%s %s\"\n", program, args));
638
639 #ifdef CREATE_NEW_PROCESS_GROUP
640 flags |= CREATE_NEW_PROCESS_GROUP;
641 #endif
642
643 ret = create_process (program, args, flags, &pi);
644 err = GetLastError ();
645 if (!ret && err == ERROR_FILE_NOT_FOUND)
646 {
647 char *exename = (char *) alloca (strlen (program) + 5);
648 strcat (strcpy (exename, program), ".exe");
649 ret = create_process (exename, args, flags, &pi);
650 err = GetLastError ();
651 }
652
653 #ifndef USE_WIN32API
654 if (orig_path)
655 setenv ("PATH", orig_path, 1);
656 #endif
657
658 if (!ret)
659 {
660 error ("Error creating process \"%s %s\", (error %d): %s\n",
661 program, args, (int) err, strwinerror (err));
662 }
663 else
664 {
665 OUTMSG2 (("Process created: %s %s\n", program, (char *) args));
666 }
667
668 CloseHandle (pi.hThread);
669
670 do_initial_child_stuff (pi.hProcess, pi.dwProcessId, 0);
671
672 /* Wait till we are at 1st instruction in program, return new pid
673 (assuming success). */
674 cs.last_ptid = wait (ptid_t (current_process_id), &cs.last_status, 0);
675
676 /* Necessary for handle_v_kill. */
677 signal_pid = current_process_id;
678
679 return current_process_id;
680 }
681
682 /* Attach to a running process.
683 PID is the process ID to attach to, specified by the user
684 or a higher layer. */
685 int
686 win32_process_target::attach (unsigned long pid)
687 {
688 HANDLE h;
689 DWORD err;
690
691 h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
692 if (h != NULL)
693 {
694 if (DebugActiveProcess (pid))
695 {
696 DebugSetProcessKillOnExit (FALSE);
697
698 /* win32_wait needs to know we're attaching. */
699 attaching = 1;
700 do_initial_child_stuff (h, pid, 1);
701 return 0;
702 }
703
704 CloseHandle (h);
705 }
706
707 err = GetLastError ();
708 error ("Attach to process failed (error %d): %s\n",
709 (int) err, strwinerror (err));
710 }
711
712 /* See nat/windows-nat.h. */
713
714 int
715 windows_nat::handle_output_debug_string (struct target_waitstatus *ourstatus)
716 {
717 #define READ_BUFFER_LEN 1024
718 CORE_ADDR addr;
719 char s[READ_BUFFER_LEN + 1] = { 0 };
720 DWORD nbytes = current_event.u.DebugString.nDebugStringLength;
721
722 if (nbytes == 0)
723 return 0;
724
725 if (nbytes > READ_BUFFER_LEN)
726 nbytes = READ_BUFFER_LEN;
727
728 addr = (CORE_ADDR) (size_t) current_event.u.DebugString.lpDebugStringData;
729
730 if (current_event.u.DebugString.fUnicode)
731 {
732 /* The event tells us how many bytes, not chars, even
733 in Unicode. */
734 WCHAR buffer[(READ_BUFFER_LEN + 1) / sizeof (WCHAR)] = { 0 };
735 if (read_inferior_memory (addr, (unsigned char *) buffer, nbytes) != 0)
736 return 0;
737 wcstombs (s, buffer, (nbytes + 1) / sizeof (WCHAR));
738 }
739 else
740 {
741 if (read_inferior_memory (addr, (unsigned char *) s, nbytes) != 0)
742 return 0;
743 }
744
745 if (!startswith (s, "cYg"))
746 {
747 if (!server_waiting)
748 {
749 OUTMSG2(("%s", s));
750 return 0;
751 }
752
753 monitor_output (s);
754 }
755 #undef READ_BUFFER_LEN
756
757 return 0;
758 }
759
760 static void
761 win32_clear_inferiors (void)
762 {
763 if (open_process_used)
764 {
765 CloseHandle (current_process_handle);
766 open_process_used = false;
767 }
768
769 for_each_thread (delete_thread_info);
770 siginfo_er.ExceptionCode = 0;
771 clear_inferiors ();
772 }
773
774 /* Implementation of target_ops::kill. */
775
776 int
777 win32_process_target::kill (process_info *process)
778 {
779 TerminateProcess (current_process_handle, 0);
780 for (;;)
781 {
782 if (!child_continue (DBG_CONTINUE, -1))
783 break;
784 if (!wait_for_debug_event (&current_event, INFINITE))
785 break;
786 if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
787 break;
788 else if (current_event.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT)
789 handle_output_debug_string (nullptr);
790 }
791
792 win32_clear_inferiors ();
793
794 remove_process (process);
795 return 0;
796 }
797
798 /* Implementation of target_ops::detach. */
799
800 int
801 win32_process_target::detach (process_info *process)
802 {
803 struct thread_resume resume;
804 resume.thread = minus_one_ptid;
805 resume.kind = resume_continue;
806 resume.sig = 0;
807 this->resume (&resume, 1);
808
809 if (!DebugActiveProcessStop (current_process_id))
810 return -1;
811
812 DebugSetProcessKillOnExit (FALSE);
813 remove_process (process);
814
815 win32_clear_inferiors ();
816 return 0;
817 }
818
819 void
820 win32_process_target::mourn (struct process_info *process)
821 {
822 remove_process (process);
823 }
824
825 /* Implementation of target_ops::join. */
826
827 void
828 win32_process_target::join (int pid)
829 {
830 HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
831 if (h != NULL)
832 {
833 WaitForSingleObject (h, INFINITE);
834 CloseHandle (h);
835 }
836 }
837
838 /* Return true iff the thread with thread ID TID is alive. */
839 bool
840 win32_process_target::thread_alive (ptid_t ptid)
841 {
842 /* Our thread list is reliable; don't bother to poll target
843 threads. */
844 return find_thread_ptid (ptid) != NULL;
845 }
846
847 /* Resume the inferior process. RESUME_INFO describes how we want
848 to resume. */
849 void
850 win32_process_target::resume (thread_resume *resume_info, size_t n)
851 {
852 DWORD tid;
853 enum gdb_signal sig;
854 int step;
855 windows_thread_info *th;
856 DWORD continue_status = DBG_CONTINUE;
857 ptid_t ptid;
858
859 /* This handles the very limited set of resume packets that GDB can
860 currently produce. */
861
862 if (n == 1 && resume_info[0].thread == minus_one_ptid)
863 tid = -1;
864 else if (n > 1)
865 tid = -1;
866 else
867 /* Yes, we're ignoring resume_info[0].thread. It'd be tricky to make
868 the Windows resume code do the right thing for thread switching. */
869 tid = current_event.dwThreadId;
870
871 if (resume_info[0].thread != minus_one_ptid)
872 {
873 sig = gdb_signal_from_host (resume_info[0].sig);
874 step = resume_info[0].kind == resume_step;
875 }
876 else
877 {
878 sig = GDB_SIGNAL_0;
879 step = 0;
880 }
881
882 if (sig != GDB_SIGNAL_0)
883 {
884 if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
885 {
886 OUTMSG (("Cannot continue with signal %s here.\n",
887 gdb_signal_to_string (sig)));
888 }
889 else if (sig == last_sig)
890 continue_status = DBG_EXCEPTION_NOT_HANDLED;
891 else
892 OUTMSG (("Can only continue with received signal %s.\n",
893 gdb_signal_to_string (last_sig)));
894 }
895
896 last_sig = GDB_SIGNAL_0;
897
898 /* Get context for the currently selected thread. */
899 ptid = debug_event_ptid (&current_event);
900 th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
901 if (th)
902 {
903 win32_prepare_to_resume (th);
904
905 DWORD *context_flags;
906 #ifdef __x86_64__
907 if (wow64_process)
908 context_flags = &th->wow64_context.ContextFlags;
909 else
910 #endif
911 context_flags = &th->context.ContextFlags;
912 if (*context_flags)
913 {
914 /* Move register values from the inferior into the thread
915 context structure. */
916 regcache_invalidate ();
917
918 if (step)
919 {
920 if (the_low_target.single_step != NULL)
921 (*the_low_target.single_step) (th);
922 else
923 error ("Single stepping is not supported "
924 "in this configuration.\n");
925 }
926
927 win32_set_thread_context (th);
928 *context_flags = 0;
929 }
930 }
931
932 /* Allow continuing with the same signal that interrupted us.
933 Otherwise complain. */
934
935 child_continue (continue_status, tid);
936 }
937
938 /* See nat/windows-nat.h. */
939
940 void
941 windows_nat::handle_load_dll (const char *name, LPVOID base)
942 {
943 CORE_ADDR load_addr = (CORE_ADDR) (uintptr_t) base;
944
945 char buf[MAX_PATH + 1];
946 char buf2[MAX_PATH + 1];
947
948 WIN32_FIND_DATAA w32_fd;
949 HANDLE h = FindFirstFileA (name, &w32_fd);
950
951 /* The symbols in a dll are offset by 0x1000, which is the
952 offset from 0 of the first byte in an image - because
953 of the file header and the section alignment. */
954 load_addr += 0x1000;
955
956 if (h == INVALID_HANDLE_VALUE)
957 strcpy (buf, name);
958 else
959 {
960 FindClose (h);
961 strcpy (buf, name);
962 {
963 char cwd[MAX_PATH + 1];
964 char *p;
965 if (GetCurrentDirectoryA (MAX_PATH + 1, cwd))
966 {
967 p = strrchr (buf, '\\');
968 if (p)
969 p[1] = '\0';
970 SetCurrentDirectoryA (buf);
971 GetFullPathNameA (w32_fd.cFileName, MAX_PATH, buf, &p);
972 SetCurrentDirectoryA (cwd);
973 }
974 }
975 }
976
977 if (strcasecmp (buf, "ntdll.dll") == 0)
978 {
979 GetSystemDirectoryA (buf, sizeof (buf));
980 strcat (buf, "\\ntdll.dll");
981 }
982
983 #ifdef __CYGWIN__
984 cygwin_conv_path (CCP_WIN_A_TO_POSIX, buf, buf2, sizeof (buf2));
985 #else
986 strcpy (buf2, buf);
987 #endif
988
989 loaded_dll (buf2, load_addr);
990 }
991
992 /* See nat/windows-nat.h. */
993
994 void
995 windows_nat::handle_unload_dll ()
996 {
997 CORE_ADDR load_addr =
998 (CORE_ADDR) (uintptr_t) current_event.u.UnloadDll.lpBaseOfDll;
999
1000 /* The symbols in a dll are offset by 0x1000, which is the
1001 offset from 0 of the first byte in an image - because
1002 of the file header and the section alignment. */
1003 load_addr += 0x1000;
1004 unloaded_dll (NULL, load_addr);
1005 }
1006
1007 static void
1008 suspend_one_thread (thread_info *thread)
1009 {
1010 windows_thread_info *th = (windows_thread_info *) thread_target_data (thread);
1011
1012 th->suspend ();
1013 }
1014
1015 static void
1016 fake_breakpoint_event (void)
1017 {
1018 OUTMSG2(("fake_breakpoint_event\n"));
1019
1020 faked_breakpoint = 1;
1021
1022 memset (&current_event, 0, sizeof (current_event));
1023 current_event.dwThreadId = main_thread_id;
1024 current_event.dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
1025 current_event.u.Exception.ExceptionRecord.ExceptionCode
1026 = EXCEPTION_BREAKPOINT;
1027
1028 for_each_thread (suspend_one_thread);
1029 }
1030
1031 /* See nat/windows-nat.h. */
1032
1033 bool
1034 windows_nat::handle_ms_vc_exception (const EXCEPTION_RECORD *rec)
1035 {
1036 return false;
1037 }
1038
1039 /* See nat/windows-nat.h. */
1040
1041 bool
1042 windows_nat::handle_access_violation (const EXCEPTION_RECORD *rec)
1043 {
1044 return false;
1045 }
1046
1047 /* A helper function that will, if needed, set
1048 'stopped_at_software_breakpoint' on the thread and adjust the
1049 PC. */
1050
1051 static void
1052 maybe_adjust_pc ()
1053 {
1054 struct regcache *regcache = get_thread_regcache (current_thread, 1);
1055 child_fetch_inferior_registers (regcache, -1);
1056
1057 windows_thread_info *th = thread_rec (current_thread_ptid (),
1058 DONT_INVALIDATE_CONTEXT);
1059 th->stopped_at_software_breakpoint = false;
1060
1061 if (current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
1062 && ((current_event.u.Exception.ExceptionRecord.ExceptionCode
1063 == EXCEPTION_BREAKPOINT)
1064 || (current_event.u.Exception.ExceptionRecord.ExceptionCode
1065 == STATUS_WX86_BREAKPOINT))
1066 && child_initialization_done)
1067 {
1068 th->stopped_at_software_breakpoint = true;
1069 CORE_ADDR pc = regcache_read_pc (regcache);
1070 CORE_ADDR sw_breakpoint_pc = pc - the_low_target.decr_pc_after_break;
1071 regcache_write_pc (regcache, sw_breakpoint_pc);
1072 }
1073 }
1074
1075 /* Get the next event from the child. */
1076
1077 static int
1078 get_child_debug_event (DWORD *continue_status,
1079 struct target_waitstatus *ourstatus)
1080 {
1081 ptid_t ptid;
1082
1083 last_sig = GDB_SIGNAL_0;
1084 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
1085 *continue_status = DBG_CONTINUE;
1086
1087 /* Check if GDB sent us an interrupt request. */
1088 check_remote_input_interrupt_request ();
1089
1090 if (soft_interrupt_requested)
1091 {
1092 soft_interrupt_requested = 0;
1093 fake_breakpoint_event ();
1094 goto gotevent;
1095 }
1096
1097 attaching = 0;
1098 {
1099 gdb::optional<pending_stop> stop = fetch_pending_stop (debug_threads);
1100 if (stop.has_value ())
1101 {
1102 *ourstatus = stop->status;
1103 current_event = stop->event;
1104 ptid = debug_event_ptid (&current_event);
1105 current_thread = find_thread_ptid (ptid);
1106 return 1;
1107 }
1108
1109 /* Keep the wait time low enough for comfortable remote
1110 interruption, but high enough so gdbserver doesn't become a
1111 bottleneck. */
1112 if (!wait_for_debug_event (&current_event, 250))
1113 {
1114 DWORD e = GetLastError();
1115
1116 if (e == ERROR_PIPE_NOT_CONNECTED)
1117 {
1118 /* This will happen if the loader fails to succesfully
1119 load the application, e.g., if the main executable
1120 tries to pull in a non-existing export from a
1121 DLL. */
1122 ourstatus->kind = TARGET_WAITKIND_EXITED;
1123 ourstatus->value.integer = 1;
1124 return 1;
1125 }
1126
1127 return 0;
1128 }
1129 }
1130
1131 gotevent:
1132
1133 switch (current_event.dwDebugEventCode)
1134 {
1135 case CREATE_THREAD_DEBUG_EVENT:
1136 OUTMSG2 (("gdbserver: kernel event CREATE_THREAD_DEBUG_EVENT "
1137 "for pid=%u tid=%x)\n",
1138 (unsigned) current_event.dwProcessId,
1139 (unsigned) current_event.dwThreadId));
1140
1141 /* Record the existence of this thread. */
1142 child_add_thread (current_event.dwProcessId,
1143 current_event.dwThreadId,
1144 current_event.u.CreateThread.hThread,
1145 current_event.u.CreateThread.lpThreadLocalBase);
1146 break;
1147
1148 case EXIT_THREAD_DEBUG_EVENT:
1149 OUTMSG2 (("gdbserver: kernel event EXIT_THREAD_DEBUG_EVENT "
1150 "for pid=%u tid=%x\n",
1151 (unsigned) current_event.dwProcessId,
1152 (unsigned) current_event.dwThreadId));
1153 child_delete_thread (current_event.dwProcessId,
1154 current_event.dwThreadId);
1155
1156 current_thread = get_first_thread ();
1157 return 1;
1158
1159 case CREATE_PROCESS_DEBUG_EVENT:
1160 OUTMSG2 (("gdbserver: kernel event CREATE_PROCESS_DEBUG_EVENT "
1161 "for pid=%u tid=%x\n",
1162 (unsigned) current_event.dwProcessId,
1163 (unsigned) current_event.dwThreadId));
1164 CloseHandle (current_event.u.CreateProcessInfo.hFile);
1165
1166 if (open_process_used)
1167 {
1168 CloseHandle (current_process_handle);
1169 open_process_used = false;
1170 }
1171
1172 current_process_handle = current_event.u.CreateProcessInfo.hProcess;
1173 main_thread_id = current_event.dwThreadId;
1174
1175 /* Add the main thread. */
1176 child_add_thread (current_event.dwProcessId,
1177 main_thread_id,
1178 current_event.u.CreateProcessInfo.hThread,
1179 current_event.u.CreateProcessInfo.lpThreadLocalBase);
1180 break;
1181
1182 case EXIT_PROCESS_DEBUG_EVENT:
1183 OUTMSG2 (("gdbserver: kernel event EXIT_PROCESS_DEBUG_EVENT "
1184 "for pid=%u tid=%x\n",
1185 (unsigned) current_event.dwProcessId,
1186 (unsigned) current_event.dwThreadId));
1187 {
1188 DWORD exit_status = current_event.u.ExitProcess.dwExitCode;
1189 /* If the exit status looks like a fatal exception, but we
1190 don't recognize the exception's code, make the original
1191 exit status value available, to avoid losing information. */
1192 int exit_signal
1193 = WIFSIGNALED (exit_status) ? WTERMSIG (exit_status) : -1;
1194 if (exit_signal == -1)
1195 {
1196 ourstatus->kind = TARGET_WAITKIND_EXITED;
1197 ourstatus->value.integer = exit_status;
1198 }
1199 else
1200 {
1201 ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
1202 ourstatus->value.sig = gdb_signal_from_host (exit_signal);
1203 }
1204 }
1205 child_continue (DBG_CONTINUE, desired_stop_thread_id);
1206 break;
1207
1208 case LOAD_DLL_DEBUG_EVENT:
1209 OUTMSG2 (("gdbserver: kernel event LOAD_DLL_DEBUG_EVENT "
1210 "for pid=%u tid=%x\n",
1211 (unsigned) current_event.dwProcessId,
1212 (unsigned) current_event.dwThreadId));
1213 CloseHandle (current_event.u.LoadDll.hFile);
1214 if (! child_initialization_done)
1215 break;
1216 dll_loaded_event ();
1217
1218 ourstatus->kind = TARGET_WAITKIND_LOADED;
1219 ourstatus->value.sig = GDB_SIGNAL_TRAP;
1220 break;
1221
1222 case UNLOAD_DLL_DEBUG_EVENT:
1223 OUTMSG2 (("gdbserver: kernel event UNLOAD_DLL_DEBUG_EVENT "
1224 "for pid=%u tid=%x\n",
1225 (unsigned) current_event.dwProcessId,
1226 (unsigned) current_event.dwThreadId));
1227 if (! child_initialization_done)
1228 break;
1229 handle_unload_dll ();
1230 ourstatus->kind = TARGET_WAITKIND_LOADED;
1231 ourstatus->value.sig = GDB_SIGNAL_TRAP;
1232 break;
1233
1234 case EXCEPTION_DEBUG_EVENT:
1235 OUTMSG2 (("gdbserver: kernel event EXCEPTION_DEBUG_EVENT "
1236 "for pid=%u tid=%x\n",
1237 (unsigned) current_event.dwProcessId,
1238 (unsigned) current_event.dwThreadId));
1239 if (handle_exception (ourstatus, debug_threads)
1240 == HANDLE_EXCEPTION_UNHANDLED)
1241 *continue_status = DBG_EXCEPTION_NOT_HANDLED;
1242 break;
1243
1244 case OUTPUT_DEBUG_STRING_EVENT:
1245 /* A message from the kernel (or Cygwin). */
1246 OUTMSG2 (("gdbserver: kernel event OUTPUT_DEBUG_STRING_EVENT "
1247 "for pid=%u tid=%x\n",
1248 (unsigned) current_event.dwProcessId,
1249 (unsigned) current_event.dwThreadId));
1250 handle_output_debug_string (nullptr);
1251 break;
1252
1253 default:
1254 OUTMSG2 (("gdbserver: kernel event unknown "
1255 "for pid=%u tid=%x code=%x\n",
1256 (unsigned) current_event.dwProcessId,
1257 (unsigned) current_event.dwThreadId,
1258 (unsigned) current_event.dwDebugEventCode));
1259 break;
1260 }
1261
1262 ptid = debug_event_ptid (&current_event);
1263
1264 if (desired_stop_thread_id != -1 && desired_stop_thread_id != ptid.lwp ())
1265 {
1266 /* Pending stop. See the comment by the definition of
1267 "pending_stops" for details on why this is needed. */
1268 OUTMSG2 (("get_windows_debug_event - "
1269 "unexpected stop in 0x%lx (expecting 0x%x)\n",
1270 ptid.lwp (), desired_stop_thread_id));
1271 maybe_adjust_pc ();
1272 pending_stops.push_back ({(DWORD) ptid.lwp (), *ourstatus, current_event});
1273 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
1274 }
1275 else
1276 current_thread = find_thread_ptid (ptid);
1277
1278 return 1;
1279 }
1280
1281 /* Wait for the inferior process to change state.
1282 STATUS will be filled in with a response code to send to GDB.
1283 Returns the signal which caused the process to stop. */
1284 ptid_t
1285 win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
1286 target_wait_flags options)
1287 {
1288 if (cached_status.kind != TARGET_WAITKIND_IGNORE)
1289 {
1290 /* The core always does a wait after creating the inferior, and
1291 do_initial_child_stuff already ran the inferior to the
1292 initial breakpoint (or an exit, if creating the process
1293 fails). Report it now. */
1294 *ourstatus = cached_status;
1295 cached_status.kind = TARGET_WAITKIND_IGNORE;
1296 return debug_event_ptid (&current_event);
1297 }
1298
1299 while (1)
1300 {
1301 DWORD continue_status;
1302 if (!get_child_debug_event (&continue_status, ourstatus))
1303 continue;
1304
1305 switch (ourstatus->kind)
1306 {
1307 case TARGET_WAITKIND_EXITED:
1308 OUTMSG2 (("Child exited with retcode = %x\n",
1309 ourstatus->value.integer));
1310 win32_clear_inferiors ();
1311 return ptid_t (current_event.dwProcessId);
1312 case TARGET_WAITKIND_STOPPED:
1313 case TARGET_WAITKIND_SIGNALLED:
1314 case TARGET_WAITKIND_LOADED:
1315 {
1316 OUTMSG2 (("Child Stopped with signal = %d \n",
1317 ourstatus->value.sig));
1318 maybe_adjust_pc ();
1319 return debug_event_ptid (&current_event);
1320 }
1321 default:
1322 OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind));
1323 /* fall-through */
1324 case TARGET_WAITKIND_SPURIOUS:
1325 /* do nothing, just continue */
1326 child_continue (continue_status, desired_stop_thread_id);
1327 break;
1328 }
1329 }
1330 }
1331
1332 /* Fetch registers from the inferior process.
1333 If REGNO is -1, fetch all registers; otherwise, fetch at least REGNO. */
1334 void
1335 win32_process_target::fetch_registers (regcache *regcache, int regno)
1336 {
1337 child_fetch_inferior_registers (regcache, regno);
1338 }
1339
1340 /* Store registers to the inferior process.
1341 If REGNO is -1, store all registers; otherwise, store at least REGNO. */
1342 void
1343 win32_process_target::store_registers (regcache *regcache, int regno)
1344 {
1345 child_store_inferior_registers (regcache, regno);
1346 }
1347
1348 /* Read memory from the inferior process. This should generally be
1349 called through read_inferior_memory, which handles breakpoint shadowing.
1350 Read LEN bytes at MEMADDR into a buffer at MYADDR. */
1351 int
1352 win32_process_target::read_memory (CORE_ADDR memaddr, unsigned char *myaddr,
1353 int len)
1354 {
1355 return child_xfer_memory (memaddr, (char *) myaddr, len, 0, 0) != len;
1356 }
1357
1358 /* Write memory to the inferior process. This should generally be
1359 called through write_inferior_memory, which handles breakpoint shadowing.
1360 Write LEN bytes from the buffer at MYADDR to MEMADDR.
1361 Returns 0 on success and errno on failure. */
1362 int
1363 win32_process_target::write_memory (CORE_ADDR memaddr,
1364 const unsigned char *myaddr, int len)
1365 {
1366 return child_xfer_memory (memaddr, (char *) myaddr, len, 1, 0) != len;
1367 }
1368
1369 /* Send an interrupt request to the inferior process. */
1370 void
1371 win32_process_target::request_interrupt ()
1372 {
1373 if (GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, current_process_id))
1374 return;
1375
1376 /* GenerateConsoleCtrlEvent can fail if process id being debugged is
1377 not a process group id.
1378 Fallback to XP/Vista 'DebugBreakProcess', which generates a
1379 breakpoint exception in the interior process. */
1380
1381 if (DebugBreakProcess (current_process_handle))
1382 return;
1383
1384 /* Last resort, suspend all threads manually. */
1385 soft_interrupt_requested = 1;
1386 }
1387
1388 bool
1389 win32_process_target::supports_hardware_single_step ()
1390 {
1391 return true;
1392 }
1393
1394 bool
1395 win32_process_target::supports_qxfer_siginfo ()
1396 {
1397 return true;
1398 }
1399
1400 /* Write Windows signal info. */
1401
1402 int
1403 win32_process_target::qxfer_siginfo (const char *annex,
1404 unsigned char *readbuf,
1405 unsigned const char *writebuf,
1406 CORE_ADDR offset, int len)
1407 {
1408 if (siginfo_er.ExceptionCode == 0)
1409 return -1;
1410
1411 if (readbuf == nullptr)
1412 return -1;
1413
1414 char *buf = (char *) &siginfo_er;
1415 size_t bufsize = sizeof (siginfo_er);
1416
1417 #ifdef __x86_64__
1418 EXCEPTION_RECORD32 er32;
1419 if (wow64_process)
1420 {
1421 buf = (char *) &er32;
1422 bufsize = sizeof (er32);
1423
1424 er32.ExceptionCode = siginfo_er.ExceptionCode;
1425 er32.ExceptionFlags = siginfo_er.ExceptionFlags;
1426 er32.ExceptionRecord = (uintptr_t) siginfo_er.ExceptionRecord;
1427 er32.ExceptionAddress = (uintptr_t) siginfo_er.ExceptionAddress;
1428 er32.NumberParameters = siginfo_er.NumberParameters;
1429 int i;
1430 for (i = 0; i < EXCEPTION_MAXIMUM_PARAMETERS; i++)
1431 er32.ExceptionInformation[i] = siginfo_er.ExceptionInformation[i];
1432 }
1433 #endif
1434
1435 if (offset > bufsize)
1436 return -1;
1437
1438 if (offset + len > bufsize)
1439 len = bufsize - offset;
1440
1441 memcpy (readbuf, buf + offset, len);
1442
1443 return len;
1444 }
1445
1446 bool
1447 win32_process_target::supports_get_tib_address ()
1448 {
1449 return true;
1450 }
1451
1452 /* Write Windows OS Thread Information Block address. */
1453
1454 int
1455 win32_process_target::get_tib_address (ptid_t ptid, CORE_ADDR *addr)
1456 {
1457 windows_thread_info *th;
1458 th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
1459 if (th == NULL)
1460 return 0;
1461 if (addr != NULL)
1462 *addr = th->thread_local_base;
1463 return 1;
1464 }
1465
1466 /* Implementation of the target_ops method "sw_breakpoint_from_kind". */
1467
1468 const gdb_byte *
1469 win32_process_target::sw_breakpoint_from_kind (int kind, int *size)
1470 {
1471 *size = the_low_target.breakpoint_len;
1472 return the_low_target.breakpoint;
1473 }
1474
1475 bool
1476 win32_process_target::stopped_by_sw_breakpoint ()
1477 {
1478 windows_thread_info *th = thread_rec (current_thread_ptid (),
1479 DONT_INVALIDATE_CONTEXT);
1480 return th == nullptr ? false : th->stopped_at_software_breakpoint;
1481 }
1482
1483 bool
1484 win32_process_target::supports_stopped_by_sw_breakpoint ()
1485 {
1486 return true;
1487 }
1488
1489 CORE_ADDR
1490 win32_process_target::read_pc (struct regcache *regcache)
1491 {
1492 return (*the_low_target.get_pc) (regcache);
1493 }
1494
1495 void
1496 win32_process_target::write_pc (struct regcache *regcache, CORE_ADDR pc)
1497 {
1498 return (*the_low_target.set_pc) (regcache, pc);
1499 }
1500
1501 /* The win32 target ops object. */
1502
1503 static win32_process_target the_win32_target;
1504
1505 /* Initialize the Win32 backend. */
1506 void
1507 initialize_low (void)
1508 {
1509 set_target_ops (&the_win32_target);
1510 the_low_target.arch_setup ();
1511
1512 initialize_loadable ();
1513 }
This page took 0.059085 seconds and 3 git commands to generate.