]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/gdbserver/win32-low.c
[gdbserver] Split a new event-loop.h file out of server.h.
[thirdparty/binutils-gdb.git] / gdb / gdbserver / win32-low.c
CommitLineData
b80864fb 1/* Low level interface to Windows debugging, for gdbserver.
28e7fd62 2 Copyright (C) 2006-2013 Free Software Foundation, Inc.
b80864fb
DJ
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
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
b80864fb
DJ
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
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
b80864fb
DJ
20
21#include "server.h"
22#include "regcache.h"
23#include "gdb/signals.h"
59a016f0 24#include "gdb/fileio.h"
ed50f18f
PA
25#include "mem-break.h"
26#include "win32-low.h"
623b6bdf 27#include "gdbthread.h"
799cdc37 28#include "dll.h"
b80864fb 29
a959a88d 30#include <stdint.h>
b80864fb 31#include <windows.h>
ed50f18f 32#include <winnt.h>
b80864fb 33#include <imagehlp.h>
255e7678 34#include <tlhelp32.h>
b80864fb 35#include <psapi.h>
b80864fb
DJ
36#include <process.h>
37
38#ifndef USE_WIN32API
39#include <sys/cygwin.h>
40#endif
41
10357975
PA
42#define OUTMSG(X) do { printf X; fflush (stderr); } while (0)
43
44#define OUTMSG2(X) \
45 do \
46 { \
47 if (debug_threads) \
48 { \
49 printf X; \
50 fflush (stderr); \
51 } \
52 } while (0)
ed50f18f
PA
53
54#ifndef _T
55#define _T(x) TEXT (x)
56#endif
57
58#ifndef COUNTOF
59#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0]))
b80864fb
DJ
60#endif
61
bf914831
PA
62#ifdef _WIN32_WCE
63# define GETPROCADDRESS(DLL, PROC) \
64 ((winapi_ ## PROC) GetProcAddress (DLL, TEXT (#PROC)))
65#else
66# define GETPROCADDRESS(DLL, PROC) \
67 ((winapi_ ## PROC) GetProcAddress (DLL, #PROC))
68#endif
69
b80864fb
DJ
70int using_threads = 1;
71
72/* Globals. */
d97903b2 73static int attaching = 0;
b80864fb
DJ
74static HANDLE current_process_handle = NULL;
75static DWORD current_process_id = 0;
5ac588cf 76static DWORD main_thread_id = 0;
a493e3e2 77static enum gdb_signal last_sig = GDB_SIGNAL_0;
b80864fb
DJ
78
79/* The current debug event from WaitForDebugEvent. */
80static DEBUG_EVENT current_event;
81
4d5d1aaa
PA
82/* Non zero if an interrupt request is to be satisfied by suspending
83 all threads. */
84static int soft_interrupt_requested = 0;
85
86/* Non zero if the inferior is stopped in a simulated breakpoint done
87 by suspending all the threads. */
88static int faked_breakpoint = 0;
89
3aee8918
PA
90const struct target_desc *win32_tdesc;
91
ed50f18f 92#define NUM_REGS (the_low_target.num_regs)
b80864fb 93
7a9a7487
MG
94typedef BOOL (WINAPI *winapi_DebugActiveProcessStop) (DWORD dwProcessId);
95typedef BOOL (WINAPI *winapi_DebugSetProcessKillOnExit) (BOOL KillOnExit);
96typedef BOOL (WINAPI *winapi_DebugBreakProcess) (HANDLE);
97typedef BOOL (WINAPI *winapi_GenerateConsoleCtrlEvent) (DWORD, DWORD);
b80864fb 98
2bd7c093 99static void win32_resume (struct thread_resume *resume_info, size_t n);
34b34921 100
b80864fb
DJ
101/* Get the thread ID from the current selected inferior (the current
102 thread). */
95954743
PA
103static ptid_t
104current_inferior_ptid (void)
b80864fb 105{
95954743
PA
106 return ((struct inferior_list_entry*) current_inferior)->id;
107}
108
109/* The current debug event from WaitForDebugEvent. */
110static ptid_t
111debug_event_ptid (DEBUG_EVENT *event)
112{
113 return ptid_build (event->dwProcessId, event->dwThreadId, 0);
b80864fb
DJ
114}
115
9c6c8194
PA
116/* Get the thread context of the thread associated with TH. */
117
118static void
119win32_get_thread_context (win32_thread_info *th)
120{
121 memset (&th->context, 0, sizeof (CONTEXT));
122 (*the_low_target.get_thread_context) (th, &current_event);
123#ifdef _WIN32_WCE
124 memcpy (&th->base_context, &th->context, sizeof (CONTEXT));
125#endif
126}
127
128/* Set the thread context of the thread associated with TH. */
129
130static void
131win32_set_thread_context (win32_thread_info *th)
132{
133#ifdef _WIN32_WCE
134 /* Calling SuspendThread on a thread that is running kernel code
135 will report that the suspending was successful, but in fact, that
136 will often not be true. In those cases, the context returned by
137 GetThreadContext will not be correct by the time the thread
138 stops, hence we can't set that context back into the thread when
139 resuming - it will most likelly crash the inferior.
140 Unfortunately, there is no way to know when the thread will
141 really stop. To work around it, we'll only write the context
142 back to the thread when either the user or GDB explicitly change
143 it between stopping and resuming. */
144 if (memcmp (&th->context, &th->base_context, sizeof (CONTEXT)) != 0)
145#endif
146 (*the_low_target.set_thread_context) (th, &current_event);
147}
148
b80864fb
DJ
149/* Find a thread record given a thread id. If GET_CONTEXT is set then
150 also retrieve the context for this thread. */
41093d81 151static win32_thread_info *
95954743 152thread_rec (ptid_t ptid, int get_context)
b80864fb
DJ
153{
154 struct thread_info *thread;
41093d81 155 win32_thread_info *th;
b80864fb 156
95954743 157 thread = (struct thread_info *) find_inferior_id (&all_threads, ptid);
b80864fb
DJ
158 if (thread == NULL)
159 return NULL;
160
161 th = inferior_target_data (thread);
c436e841 162 if (get_context && th->context.ContextFlags == 0)
b80864fb 163 {
c436e841
PA
164 if (!th->suspended)
165 {
166 if (SuspendThread (th->h) == (DWORD) -1)
167 {
168 DWORD err = GetLastError ();
169 OUTMSG (("warning: SuspendThread failed in thread_rec, "
170 "(error %d): %s\n", (int) err, strwinerror (err)));
171 }
172 else
173 th->suspended = 1;
174 }
b80864fb 175
9c6c8194 176 win32_get_thread_context (th);
b80864fb
DJ
177 }
178
179 return th;
180}
181
182/* Add a thread to the thread list. */
41093d81 183static win32_thread_info *
711e434b 184child_add_thread (DWORD pid, DWORD tid, HANDLE h, void *tlb)
b80864fb 185{
41093d81 186 win32_thread_info *th;
95954743 187 ptid_t ptid = ptid_build (pid, tid, 0);
b80864fb 188
95954743 189 if ((th = thread_rec (ptid, FALSE)))
b80864fb
DJ
190 return th;
191
bca929d3 192 th = xcalloc (1, sizeof (*th));
b80864fb
DJ
193 th->tid = tid;
194 th->h = h;
711e434b 195 th->thread_local_base = (CORE_ADDR) (uintptr_t) tlb;
b80864fb 196
95954743 197 add_thread (ptid, th);
b80864fb 198
34b34921
PA
199 if (the_low_target.thread_added != NULL)
200 (*the_low_target.thread_added) (th);
b80864fb
DJ
201
202 return th;
203}
204
205/* Delete a thread from the list of threads. */
206static void
207delete_thread_info (struct inferior_list_entry *thread)
208{
41093d81 209 win32_thread_info *th = inferior_target_data ((struct thread_info *) thread);
b80864fb
DJ
210
211 remove_thread ((struct thread_info *) thread);
212 CloseHandle (th->h);
213 free (th);
214}
215
216/* Delete a thread from the list of threads. */
217static void
95954743 218child_delete_thread (DWORD pid, DWORD tid)
b80864fb
DJ
219{
220 struct inferior_list_entry *thread;
95954743 221 ptid_t ptid;
b80864fb
DJ
222
223 /* If the last thread is exiting, just return. */
224 if (all_threads.head == all_threads.tail)
225 return;
226
95954743
PA
227 ptid = ptid_build (pid, tid, 0);
228 thread = find_inferior_id (&all_threads, ptid);
b80864fb
DJ
229 if (thread == NULL)
230 return;
231
232 delete_thread_info (thread);
233}
234
aa5ca48f
DE
235/* These watchpoint related wrapper functions simply pass on the function call
236 if the low target has registered a corresponding function. */
237
238static int
239win32_insert_point (char type, CORE_ADDR addr, int len)
240{
241 if (the_low_target.insert_point != NULL)
242 return the_low_target.insert_point (type, addr, len);
243 else
244 /* Unsupported (see target.h). */
245 return 1;
246}
247
248static int
249win32_remove_point (char type, CORE_ADDR addr, int len)
250{
251 if (the_low_target.remove_point != NULL)
252 return the_low_target.remove_point (type, addr, len);
253 else
254 /* Unsupported (see target.h). */
255 return 1;
256}
257
258static int
259win32_stopped_by_watchpoint (void)
260{
261 if (the_low_target.stopped_by_watchpoint != NULL)
262 return the_low_target.stopped_by_watchpoint ();
263 else
264 return 0;
265}
266
267static CORE_ADDR
268win32_stopped_data_address (void)
269{
270 if (the_low_target.stopped_data_address != NULL)
271 return the_low_target.stopped_data_address ();
272 else
273 return 0;
274}
275
276
b80864fb
DJ
277/* Transfer memory from/to the debugged process. */
278static int
279child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
280 int write, struct target_ops *target)
281{
cee83bcb
PM
282 BOOL success;
283 SIZE_T done = 0;
284 DWORD lasterror = 0;
e8f0053d 285 uintptr_t addr = (uintptr_t) memaddr;
b80864fb
DJ
286
287 if (write)
288 {
cee83bcb
PM
289 success = WriteProcessMemory (current_process_handle, (LPVOID) addr,
290 (LPCVOID) our, len, &done);
291 if (!success)
292 lasterror = GetLastError ();
b80864fb
DJ
293 FlushInstructionCache (current_process_handle, (LPCVOID) addr, len);
294 }
295 else
296 {
cee83bcb
PM
297 success = ReadProcessMemory (current_process_handle, (LPCVOID) addr,
298 (LPVOID) our, len, &done);
299 if (!success)
300 lasterror = GetLastError ();
b80864fb 301 }
cee83bcb
PM
302 if (!success && lasterror == ERROR_PARTIAL_COPY && done > 0)
303 return done;
304 else
305 return success ? done : -1;
b80864fb
DJ
306}
307
ed50f18f 308/* Clear out any old thread list and reinitialize it to a pristine
b80864fb
DJ
309 state. */
310static void
311child_init_thread_list (void)
312{
313 for_each_inferior (&all_threads, delete_thread_info);
314}
315
316static void
95954743 317do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
b80864fb 318{
3aee8918
PA
319 struct process_info *proc;
320
a493e3e2 321 last_sig = GDB_SIGNAL_0;
b80864fb 322
5ac588cf
PA
323 current_process_handle = proch;
324 current_process_id = pid;
325 main_thread_id = 0;
326
327 soft_interrupt_requested = 0;
328 faked_breakpoint = 0;
329
b80864fb
DJ
330 memset (&current_event, 0, sizeof (current_event));
331
3aee8918
PA
332 proc = add_process (pid, attached);
333 proc->tdesc = win32_tdesc;
b80864fb 334 child_init_thread_list ();
ed50f18f
PA
335
336 if (the_low_target.initial_stuff != NULL)
337 (*the_low_target.initial_stuff) ();
b80864fb
DJ
338}
339
340/* Resume all artificially suspended threads if we are continuing
341 execution. */
342static int
343continue_one_thread (struct inferior_list_entry *this_thread, void *id_ptr)
344{
345 struct thread_info *thread = (struct thread_info *) this_thread;
346 int thread_id = * (int *) id_ptr;
41093d81 347 win32_thread_info *th = inferior_target_data (thread);
b80864fb
DJ
348
349 if ((thread_id == -1 || thread_id == th->tid)
c436e841 350 && th->suspended)
b80864fb 351 {
34b34921 352 if (th->context.ContextFlags)
b80864fb 353 {
9c6c8194 354 win32_set_thread_context (th);
b80864fb
DJ
355 th->context.ContextFlags = 0;
356 }
34b34921 357
c436e841
PA
358 if (ResumeThread (th->h) == (DWORD) -1)
359 {
360 DWORD err = GetLastError ();
361 OUTMSG (("warning: ResumeThread failed in continue_one_thread, "
362 "(error %d): %s\n", (int) err, strwinerror (err)));
363 }
364 th->suspended = 0;
b80864fb
DJ
365 }
366
367 return 0;
368}
369
370static BOOL
371child_continue (DWORD continue_status, int thread_id)
372{
4d5d1aaa
PA
373 /* The inferior will only continue after the ContinueDebugEvent
374 call. */
375 find_inferior (&all_threads, continue_one_thread, &thread_id);
376 faked_breakpoint = 0;
b80864fb 377
4d5d1aaa
PA
378 if (!ContinueDebugEvent (current_event.dwProcessId,
379 current_event.dwThreadId,
380 continue_status))
381 return FALSE;
b80864fb 382
4d5d1aaa 383 return TRUE;
b80864fb
DJ
384}
385
b80864fb
DJ
386/* Fetch register(s) from the current thread context. */
387static void
442ea881 388child_fetch_inferior_registers (struct regcache *regcache, int r)
b80864fb
DJ
389{
390 int regno;
95954743 391 win32_thread_info *th = thread_rec (current_inferior_ptid (), TRUE);
4463ce24 392 if (r == -1 || r > NUM_REGS)
442ea881 393 child_fetch_inferior_registers (regcache, NUM_REGS);
b80864fb
DJ
394 else
395 for (regno = 0; regno < r; regno++)
442ea881 396 (*the_low_target.fetch_inferior_register) (regcache, th, regno);
b80864fb
DJ
397}
398
399/* Store a new register value into the current thread context. We don't
400 change the program's context until later, when we resume it. */
401static void
442ea881 402child_store_inferior_registers (struct regcache *regcache, int r)
b80864fb
DJ
403{
404 int regno;
95954743 405 win32_thread_info *th = thread_rec (current_inferior_ptid (), TRUE);
b80864fb 406 if (r == -1 || r == 0 || r > NUM_REGS)
442ea881 407 child_store_inferior_registers (regcache, NUM_REGS);
b80864fb
DJ
408 else
409 for (regno = 0; regno < r; regno++)
442ea881 410 (*the_low_target.store_inferior_register) (regcache, th, regno);
b80864fb
DJ
411}
412
ed50f18f
PA
413/* Map the Windows error number in ERROR to a locale-dependent error
414 message string and return a pointer to it. Typically, the values
415 for ERROR come from GetLastError.
416
417 The string pointed to shall not be modified by the application,
418 but may be overwritten by a subsequent call to strwinerror
419
420 The strwinerror function does not change the current setting
421 of GetLastError. */
422
423char *
424strwinerror (DWORD error)
425{
426 static char buf[1024];
427 TCHAR *msgbuf;
428 DWORD lasterr = GetLastError ();
429 DWORD chars = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
430 | FORMAT_MESSAGE_ALLOCATE_BUFFER,
431 NULL,
432 error,
433 0, /* Default language */
434 (LPVOID)&msgbuf,
435 0,
436 NULL);
437 if (chars != 0)
438 {
439 /* If there is an \r\n appended, zap it. */
440 if (chars >= 2
441 && msgbuf[chars - 2] == '\r'
442 && msgbuf[chars - 1] == '\n')
443 {
444 chars -= 2;
445 msgbuf[chars] = 0;
446 }
447
448 if (chars > ((COUNTOF (buf)) - 1))
449 {
450 chars = COUNTOF (buf) - 1;
451 msgbuf [chars] = 0;
452 }
453
454#ifdef UNICODE
455 wcstombs (buf, msgbuf, chars + 1);
456#else
457 strncpy (buf, msgbuf, chars + 1);
458#endif
459 LocalFree (msgbuf);
460 }
461 else
dfe07582 462 sprintf (buf, "unknown win32 error (%u)", (unsigned) error);
ed50f18f
PA
463
464 SetLastError (lasterr);
465 return buf;
466}
467
aec18585
PA
468static BOOL
469create_process (const char *program, char *args,
470 DWORD flags, PROCESS_INFORMATION *pi)
471{
472 BOOL ret;
473
474#ifdef _WIN32_WCE
475 wchar_t *p, *wprogram, *wargs;
476 size_t argslen;
477
478 wprogram = alloca ((strlen (program) + 1) * sizeof (wchar_t));
479 mbstowcs (wprogram, program, strlen (program) + 1);
480
481 for (p = wprogram; *p; ++p)
482 if (L'/' == *p)
483 *p = L'\\';
484
485 argslen = strlen (args);
486 wargs = alloca ((argslen + 1) * sizeof (wchar_t));
487 mbstowcs (wargs, args, argslen + 1);
488
489 ret = CreateProcessW (wprogram, /* image name */
1b3f6016
PA
490 wargs, /* command line */
491 NULL, /* security, not supported */
492 NULL, /* thread, not supported */
493 FALSE, /* inherit handles, not supported */
494 flags, /* start flags */
495 NULL, /* environment, not supported */
496 NULL, /* current directory, not supported */
497 NULL, /* start info, not supported */
498 pi); /* proc info */
aec18585
PA
499#else
500 STARTUPINFOA si = { sizeof (STARTUPINFOA) };
501
502 ret = CreateProcessA (program, /* image name */
503 args, /* command line */
504 NULL, /* security */
505 NULL, /* thread */
506 TRUE, /* inherit handles */
507 flags, /* start flags */
508 NULL, /* environment */
509 NULL, /* current directory */
510 &si, /* start info */
511 pi); /* proc info */
512#endif
513
514 return ret;
515}
516
b80864fb
DJ
517/* Start a new process.
518 PROGRAM is a path to the program to execute.
519 ARGS is a standard NULL-terminated array of arguments,
520 to be passed to the inferior as ``argv''.
521 Returns the new PID on success, -1 on failure. Registers the new
522 process with the process list. */
523static int
524win32_create_inferior (char *program, char **program_args)
525{
526#ifndef USE_WIN32API
d8d2a3ee 527 char real_path[PATH_MAX];
b80864fb
DJ
528 char *orig_path, *new_path, *path_ptr;
529#endif
b80864fb
DJ
530 BOOL ret;
531 DWORD flags;
532 char *args;
533 int argslen;
534 int argc;
ed50f18f 535 PROCESS_INFORMATION pi;
aec18585 536 DWORD err;
b80864fb 537
d97903b2
PA
538 /* win32_wait needs to know we're not attaching. */
539 attaching = 0;
540
b80864fb
DJ
541 if (!program)
542 error ("No executable specified, specify executable to debug.\n");
543
b80864fb
DJ
544 flags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
545
546#ifndef USE_WIN32API
547 orig_path = NULL;
548 path_ptr = getenv ("PATH");
549 if (path_ptr)
550 {
81239425 551 int size = cygwin_conv_path_list (CCP_POSIX_TO_WIN_A, path_ptr, NULL, 0);
b80864fb 552 orig_path = alloca (strlen (path_ptr) + 1);
81239425 553 new_path = alloca (size);
b80864fb 554 strcpy (orig_path, path_ptr);
81239425 555 cygwin_conv_path_list (CCP_POSIX_TO_WIN_A, path_ptr, new_path, size);
b80864fb 556 setenv ("PATH", new_path, 1);
81239425 557 }
d8d2a3ee 558 cygwin_conv_path (CCP_POSIX_TO_WIN_A, program, real_path, PATH_MAX);
b80864fb
DJ
559 program = real_path;
560#endif
561
ed50f18f 562 argslen = 1;
b80864fb
DJ
563 for (argc = 1; program_args[argc]; argc++)
564 argslen += strlen (program_args[argc]) + 1;
565 args = alloca (argslen);
ed50f18f 566 args[0] = '\0';
b80864fb
DJ
567 for (argc = 1; program_args[argc]; argc++)
568 {
569 /* FIXME: Can we do better about quoting? How does Cygwin
1b3f6016 570 handle this? */
b80864fb
DJ
571 strcat (args, " ");
572 strcat (args, program_args[argc]);
573 }
ed50f18f 574 OUTMSG2 (("Command line is \"%s\"\n", args));
b80864fb 575
ed50f18f 576#ifdef CREATE_NEW_PROCESS_GROUP
b80864fb 577 flags |= CREATE_NEW_PROCESS_GROUP;
ed50f18f 578#endif
b80864fb 579
aec18585
PA
580 ret = create_process (program, args, flags, &pi);
581 err = GetLastError ();
582 if (!ret && err == ERROR_FILE_NOT_FOUND)
583 {
584 char *exename = alloca (strlen (program) + 5);
585 strcat (strcpy (exename, program), ".exe");
586 ret = create_process (exename, args, flags, &pi);
587 err = GetLastError ();
588 }
b80864fb
DJ
589
590#ifndef USE_WIN32API
591 if (orig_path)
592 setenv ("PATH", orig_path, 1);
593#endif
594
595 if (!ret)
596 {
ed50f18f
PA
597 error ("Error creating process \"%s%s\", (error %d): %s\n",
598 program, args, (int) err, strwinerror (err));
b80864fb
DJ
599 }
600 else
601 {
602 OUTMSG2 (("Process created: %s\n", (char *) args));
603 }
604
ed50f18f
PA
605#ifndef _WIN32_WCE
606 /* On Windows CE this handle can't be closed. The OS reuses
607 it in the debug events, while the 9x/NT versions of Windows
608 probably use a DuplicateHandle'd one. */
b80864fb 609 CloseHandle (pi.hThread);
ed50f18f 610#endif
b80864fb 611
95954743 612 do_initial_child_stuff (pi.hProcess, pi.dwProcessId, 0);
b80864fb
DJ
613
614 return current_process_id;
615}
616
617/* Attach to a running process.
618 PID is the process ID to attach to, specified by the user
619 or a higher layer. */
620static int
621win32_attach (unsigned long pid)
622{
5ca906e6 623 HANDLE h;
bf914831 624 winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
5ca906e6 625 DWORD err;
ed50f18f
PA
626#ifdef _WIN32_WCE
627 HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
628#else
629 HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
630#endif
bf914831 631 DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit);
b80864fb 632
5ca906e6
PA
633 h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
634 if (h != NULL)
1d5315fe 635 {
5ca906e6
PA
636 if (DebugActiveProcess (pid))
637 {
638 if (DebugSetProcessKillOnExit != NULL)
639 DebugSetProcessKillOnExit (FALSE);
640
d97903b2 641 /* win32_wait needs to know we're attaching. */
1b3f6016 642 attaching = 1;
95954743 643 do_initial_child_stuff (h, pid, 1);
5ca906e6
PA
644 return 0;
645 }
646
647 CloseHandle (h);
b80864fb
DJ
648 }
649
5ca906e6
PA
650 err = GetLastError ();
651 error ("Attach to process failed (error %d): %s\n",
652 (int) err, strwinerror (err));
b80864fb
DJ
653}
654
bce7165d
PA
655/* Handle OUTPUT_DEBUG_STRING_EVENT from child process. */
656static void
657handle_output_debug_string (struct target_waitstatus *ourstatus)
658{
659#define READ_BUFFER_LEN 1024
660 CORE_ADDR addr;
661 char s[READ_BUFFER_LEN + 1] = { 0 };
662 DWORD nbytes = current_event.u.DebugString.nDebugStringLength;
663
664 if (nbytes == 0)
665 return;
666
667 if (nbytes > READ_BUFFER_LEN)
668 nbytes = READ_BUFFER_LEN;
669
670 addr = (CORE_ADDR) (size_t) current_event.u.DebugString.lpDebugStringData;
671
672 if (current_event.u.DebugString.fUnicode)
673 {
674 /* The event tells us how many bytes, not chars, even
1b3f6016 675 in Unicode. */
bce7165d
PA
676 WCHAR buffer[(READ_BUFFER_LEN + 1) / sizeof (WCHAR)] = { 0 };
677 if (read_inferior_memory (addr, (unsigned char *) buffer, nbytes) != 0)
678 return;
679 wcstombs (s, buffer, (nbytes + 1) / sizeof (WCHAR));
680 }
681 else
682 {
683 if (read_inferior_memory (addr, (unsigned char *) s, nbytes) != 0)
684 return;
685 }
686
687 if (strncmp (s, "cYg", 3) != 0)
45e2715e
PA
688 {
689 if (!server_waiting)
690 {
691 OUTMSG2(("%s", s));
692 return;
693 }
694
695 monitor_output (s);
696 }
bce7165d
PA
697#undef READ_BUFFER_LEN
698}
699
5ac588cf
PA
700static void
701win32_clear_inferiors (void)
702{
703 if (current_process_handle != NULL)
704 CloseHandle (current_process_handle);
705
706 for_each_inferior (&all_threads, delete_thread_info);
707 clear_inferiors ();
708}
709
b80864fb 710/* Kill all inferiors. */
95954743
PA
711static int
712win32_kill (int pid)
b80864fb 713{
95954743
PA
714 struct process_info *process;
715
9d606399 716 if (current_process_handle == NULL)
95954743 717 return -1;
9d606399 718
b80864fb
DJ
719 TerminateProcess (current_process_handle, 0);
720 for (;;)
721 {
722 if (!child_continue (DBG_CONTINUE, -1))
723 break;
724 if (!WaitForDebugEvent (&current_event, INFINITE))
725 break;
726 if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
727 break;
bce7165d
PA
728 else if (current_event.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT)
729 {
1b3f6016 730 struct target_waitstatus our_status = { 0 };
bce7165d 731 handle_output_debug_string (&our_status);
1b3f6016 732 }
b80864fb 733 }
ed50f18f 734
5ac588cf 735 win32_clear_inferiors ();
95954743
PA
736
737 process = find_process_pid (pid);
738 remove_process (process);
739 return 0;
b80864fb
DJ
740}
741
95954743 742/* Detach from inferior PID. */
444d6139 743static int
95954743 744win32_detach (int pid)
b80864fb 745{
95954743 746 struct process_info *process;
bf914831
PA
747 winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL;
748 winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
ed50f18f
PA
749#ifdef _WIN32_WCE
750 HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
751#else
752 HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
753#endif
bf914831
PA
754 DebugActiveProcessStop = GETPROCADDRESS (dll, DebugActiveProcessStop);
755 DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit);
b80864fb 756
444d6139
PA
757 if (DebugSetProcessKillOnExit == NULL
758 || DebugActiveProcessStop == NULL)
759 return -1;
b80864fb 760
444d6139
PA
761 {
762 struct thread_resume resume;
95954743 763 resume.thread = minus_one_ptid;
bd99dc85 764 resume.kind = resume_continue;
444d6139 765 resume.sig = 0;
2bd7c093 766 win32_resume (&resume, 1);
444d6139
PA
767 }
768
769 if (!DebugActiveProcessStop (current_process_id))
5ac588cf
PA
770 return -1;
771
444d6139 772 DebugSetProcessKillOnExit (FALSE);
95954743
PA
773 process = find_process_pid (pid);
774 remove_process (process);
444d6139 775
5ac588cf 776 win32_clear_inferiors ();
444d6139
PA
777 return 0;
778}
779
505106cd
PA
780static void
781win32_mourn (struct process_info *process)
782{
783 remove_process (process);
784}
785
444d6139
PA
786/* Wait for inferiors to end. */
787static void
95954743 788win32_join (int pid)
444d6139 789{
95954743 790 HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
5ac588cf
PA
791 if (h != NULL)
792 {
793 WaitForSingleObject (h, INFINITE);
794 CloseHandle (h);
795 }
b80864fb
DJ
796}
797
798/* Return 1 iff the thread with thread ID TID is alive. */
799static int
95954743 800win32_thread_alive (ptid_t ptid)
b80864fb
DJ
801{
802 int res;
803
804 /* Our thread list is reliable; don't bother to poll target
805 threads. */
95954743 806 if (find_inferior_id (&all_threads, ptid) != NULL)
b80864fb
DJ
807 res = 1;
808 else
809 res = 0;
810 return res;
811}
812
813/* Resume the inferior process. RESUME_INFO describes how we want
814 to resume. */
815static void
2bd7c093 816win32_resume (struct thread_resume *resume_info, size_t n)
b80864fb
DJ
817{
818 DWORD tid;
2ea28649 819 enum gdb_signal sig;
b80864fb 820 int step;
41093d81 821 win32_thread_info *th;
b80864fb 822 DWORD continue_status = DBG_CONTINUE;
95954743 823 ptid_t ptid;
b80864fb
DJ
824
825 /* This handles the very limited set of resume packets that GDB can
826 currently produce. */
827
95954743 828 if (n == 1 && ptid_equal (resume_info[0].thread, minus_one_ptid))
b80864fb 829 tid = -1;
2bd7c093 830 else if (n > 1)
b80864fb
DJ
831 tid = -1;
832 else
833 /* Yes, we're ignoring resume_info[0].thread. It'd be tricky to make
834 the Windows resume code do the right thing for thread switching. */
835 tid = current_event.dwThreadId;
836
95954743 837 if (!ptid_equal (resume_info[0].thread, minus_one_ptid))
b80864fb
DJ
838 {
839 sig = resume_info[0].sig;
bd99dc85 840 step = resume_info[0].kind == resume_step;
b80864fb
DJ
841 }
842 else
843 {
844 sig = 0;
845 step = 0;
846 }
847
a493e3e2 848 if (sig != GDB_SIGNAL_0)
b80864fb
DJ
849 {
850 if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
851 {
852 OUTMSG (("Cannot continue with signal %d here.\n", sig));
853 }
854 else if (sig == last_sig)
855 continue_status = DBG_EXCEPTION_NOT_HANDLED;
856 else
857 OUTMSG (("Can only continue with recieved signal %d.\n", last_sig));
858 }
859
a493e3e2 860 last_sig = GDB_SIGNAL_0;
b80864fb
DJ
861
862 /* Get context for the currently selected thread. */
95954743
PA
863 ptid = debug_event_ptid (&current_event);
864 th = thread_rec (ptid, FALSE);
b80864fb
DJ
865 if (th)
866 {
867 if (th->context.ContextFlags)
868 {
b80864fb
DJ
869 /* Move register values from the inferior into the thread
870 context structure. */
871 regcache_invalidate ();
872
873 if (step)
ed50f18f
PA
874 {
875 if (the_low_target.single_step != NULL)
876 (*the_low_target.single_step) (th);
877 else
878 error ("Single stepping is not supported "
879 "in this configuration.\n");
880 }
34b34921 881
9c6c8194 882 win32_set_thread_context (th);
b80864fb
DJ
883 th->context.ContextFlags = 0;
884 }
885 }
886
887 /* Allow continuing with the same signal that interrupted us.
888 Otherwise complain. */
889
890 child_continue (continue_status, tid);
891}
892
255e7678
DJ
893static void
894win32_add_one_solib (const char *name, CORE_ADDR load_addr)
895{
896 char buf[MAX_PATH + 1];
897 char buf2[MAX_PATH + 1];
898
899#ifdef _WIN32_WCE
900 WIN32_FIND_DATA w32_fd;
901 WCHAR wname[MAX_PATH + 1];
902 mbstowcs (wname, name, MAX_PATH);
903 HANDLE h = FindFirstFile (wname, &w32_fd);
904#else
905 WIN32_FIND_DATAA w32_fd;
906 HANDLE h = FindFirstFileA (name, &w32_fd);
907#endif
908
909 if (h == INVALID_HANDLE_VALUE)
910 strcpy (buf, name);
911 else
912 {
913 FindClose (h);
914 strcpy (buf, name);
915#ifndef _WIN32_WCE
916 {
917 char cwd[MAX_PATH + 1];
918 char *p;
919 if (GetCurrentDirectoryA (MAX_PATH + 1, cwd))
920 {
921 p = strrchr (buf, '\\');
922 if (p)
923 p[1] = '\0';
924 SetCurrentDirectoryA (buf);
925 GetFullPathNameA (w32_fd.cFileName, MAX_PATH, buf, &p);
926 SetCurrentDirectoryA (cwd);
927 }
928 }
929#endif
930 }
931
cf6e3471
PA
932#ifndef _WIN32_WCE
933 if (strcasecmp (buf, "ntdll.dll") == 0)
934 {
935 GetSystemDirectoryA (buf, sizeof (buf));
936 strcat (buf, "\\ntdll.dll");
937 }
938#endif
939
255e7678 940#ifdef __CYGWIN__
81239425 941 cygwin_conv_path (CCP_WIN_A_TO_POSIX, buf, buf2, sizeof (buf2));
255e7678
DJ
942#else
943 strcpy (buf2, buf);
944#endif
945
946 loaded_dll (buf2, load_addr);
947}
948
949static char *
950get_image_name (HANDLE h, void *address, int unicode)
951{
952 static char buf[(2 * MAX_PATH) + 1];
953 DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
954 char *address_ptr;
955 int len = 0;
956 char b[2];
e8f0053d 957 SIZE_T done;
255e7678
DJ
958
959 /* Attempt to read the name of the dll that was detected.
960 This is documented to work only when actively debugging
961 a program. It will not work for attached processes. */
962 if (address == NULL)
963 return NULL;
964
965#ifdef _WIN32_WCE
966 /* Windows CE reports the address of the image name,
967 instead of an address of a pointer into the image name. */
968 address_ptr = address;
969#else
970 /* See if we could read the address of a string, and that the
971 address isn't null. */
972 if (!ReadProcessMemory (h, address, &address_ptr,
973 sizeof (address_ptr), &done)
974 || done != sizeof (address_ptr)
975 || !address_ptr)
976 return NULL;
977#endif
978
979 /* Find the length of the string */
980 while (ReadProcessMemory (h, address_ptr + len++ * size, &b, size, &done)
981 && (b[0] != 0 || b[size - 1] != 0) && done == size)
982 continue;
983
984 if (!unicode)
985 ReadProcessMemory (h, address_ptr, buf, len, &done);
986 else
987 {
988 WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR));
989 ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
990 &done);
991
992 WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, len, 0, 0);
993 }
994
995 return buf;
996}
997
998typedef BOOL (WINAPI *winapi_EnumProcessModules) (HANDLE, HMODULE *,
999 DWORD, LPDWORD);
1000typedef BOOL (WINAPI *winapi_GetModuleInformation) (HANDLE, HMODULE,
1001 LPMODULEINFO, DWORD);
1002typedef DWORD (WINAPI *winapi_GetModuleFileNameExA) (HANDLE, HMODULE,
1003 LPSTR, DWORD);
1004
1005static winapi_EnumProcessModules win32_EnumProcessModules;
1006static winapi_GetModuleInformation win32_GetModuleInformation;
1007static winapi_GetModuleFileNameExA win32_GetModuleFileNameExA;
1008
1009static BOOL
1010load_psapi (void)
1011{
1012 static int psapi_loaded = 0;
1013 static HMODULE dll = NULL;
1014
1015 if (!psapi_loaded)
1016 {
1017 psapi_loaded = 1;
1018 dll = LoadLibrary (TEXT("psapi.dll"));
1019 if (!dll)
1020 return FALSE;
1021 win32_EnumProcessModules =
1022 GETPROCADDRESS (dll, EnumProcessModules);
1023 win32_GetModuleInformation =
1024 GETPROCADDRESS (dll, GetModuleInformation);
1025 win32_GetModuleFileNameExA =
1026 GETPROCADDRESS (dll, GetModuleFileNameExA);
1027 }
1028
1029 return (win32_EnumProcessModules != NULL
1030 && win32_GetModuleInformation != NULL
1031 && win32_GetModuleFileNameExA != NULL);
1032}
1033
1034static int
e8f0053d 1035psapi_get_dll_name (LPVOID BaseAddress, char *dll_name_ret)
255e7678
DJ
1036{
1037 DWORD len;
1038 MODULEINFO mi;
1039 size_t i;
1040 HMODULE dh_buf[1];
1041 HMODULE *DllHandle = dh_buf;
1042 DWORD cbNeeded;
1043 BOOL ok;
1044
1045 if (!load_psapi ())
1046 goto failed;
1047
1048 cbNeeded = 0;
1049 ok = (*win32_EnumProcessModules) (current_process_handle,
1050 DllHandle,
1051 sizeof (HMODULE),
1052 &cbNeeded);
1053
1054 if (!ok || !cbNeeded)
1055 goto failed;
1056
1057 DllHandle = (HMODULE *) alloca (cbNeeded);
1058 if (!DllHandle)
1059 goto failed;
1060
1061 ok = (*win32_EnumProcessModules) (current_process_handle,
1062 DllHandle,
1063 cbNeeded,
1064 &cbNeeded);
1065 if (!ok)
1066 goto failed;
1067
1068 for (i = 0; i < ((size_t) cbNeeded / sizeof (HMODULE)); i++)
1069 {
1070 if (!(*win32_GetModuleInformation) (current_process_handle,
1071 DllHandle[i],
1072 &mi,
1073 sizeof (mi)))
1074 {
1075 DWORD err = GetLastError ();
1076 error ("Can't get module info: (error %d): %s\n",
1077 (int) err, strwinerror (err));
1078 }
1079
e8f0053d 1080 if (mi.lpBaseOfDll == BaseAddress)
255e7678
DJ
1081 {
1082 len = (*win32_GetModuleFileNameExA) (current_process_handle,
1083 DllHandle[i],
1084 dll_name_ret,
1085 MAX_PATH);
1086 if (len == 0)
1087 {
1088 DWORD err = GetLastError ();
1089 error ("Error getting dll name: (error %d): %s\n",
1090 (int) err, strwinerror (err));
1091 }
1092 return 1;
1093 }
1094 }
1095
1096failed:
1097 dll_name_ret[0] = '\0';
1098 return 0;
1099}
1100
1101typedef HANDLE (WINAPI *winapi_CreateToolhelp32Snapshot) (DWORD, DWORD);
1102typedef BOOL (WINAPI *winapi_Module32First) (HANDLE, LPMODULEENTRY32);
1103typedef BOOL (WINAPI *winapi_Module32Next) (HANDLE, LPMODULEENTRY32);
1104
1105static winapi_CreateToolhelp32Snapshot win32_CreateToolhelp32Snapshot;
1106static winapi_Module32First win32_Module32First;
1107static winapi_Module32Next win32_Module32Next;
6b3d9b83
PA
1108#ifdef _WIN32_WCE
1109typedef BOOL (WINAPI *winapi_CloseToolhelp32Snapshot) (HANDLE);
1110static winapi_CloseToolhelp32Snapshot win32_CloseToolhelp32Snapshot;
1111#endif
255e7678
DJ
1112
1113static BOOL
1114load_toolhelp (void)
1115{
1116 static int toolhelp_loaded = 0;
1117 static HMODULE dll = NULL;
1118
1119 if (!toolhelp_loaded)
1120 {
1121 toolhelp_loaded = 1;
1122#ifndef _WIN32_WCE
1123 dll = GetModuleHandle (_T("KERNEL32.DLL"));
1124#else
6b3d9b83 1125 dll = LoadLibrary (L"TOOLHELP.DLL");
255e7678
DJ
1126#endif
1127 if (!dll)
1128 return FALSE;
1129
1130 win32_CreateToolhelp32Snapshot =
1131 GETPROCADDRESS (dll, CreateToolhelp32Snapshot);
1132 win32_Module32First = GETPROCADDRESS (dll, Module32First);
1133 win32_Module32Next = GETPROCADDRESS (dll, Module32Next);
6b3d9b83
PA
1134#ifdef _WIN32_WCE
1135 win32_CloseToolhelp32Snapshot =
1136 GETPROCADDRESS (dll, CloseToolhelp32Snapshot);
1137#endif
255e7678
DJ
1138 }
1139
1140 return (win32_CreateToolhelp32Snapshot != NULL
1141 && win32_Module32First != NULL
6b3d9b83
PA
1142 && win32_Module32Next != NULL
1143#ifdef _WIN32_WCE
1144 && win32_CloseToolhelp32Snapshot != NULL
1145#endif
1146 );
255e7678
DJ
1147}
1148
1149static int
e8f0053d 1150toolhelp_get_dll_name (LPVOID BaseAddress, char *dll_name_ret)
255e7678
DJ
1151{
1152 HANDLE snapshot_module;
1153 MODULEENTRY32 modEntry = { sizeof (MODULEENTRY32) };
6b3d9b83 1154 int found = 0;
255e7678
DJ
1155
1156 if (!load_toolhelp ())
1157 return 0;
1158
1159 snapshot_module = win32_CreateToolhelp32Snapshot (TH32CS_SNAPMODULE,
1160 current_event.dwProcessId);
1161 if (snapshot_module == INVALID_HANDLE_VALUE)
1162 return 0;
1163
1164 /* Ignore the first module, which is the exe. */
6b3d9b83
PA
1165 if (win32_Module32First (snapshot_module, &modEntry))
1166 while (win32_Module32Next (snapshot_module, &modEntry))
e8f0053d 1167 if (modEntry.modBaseAddr == BaseAddress)
6b3d9b83 1168 {
255e7678 1169#ifdef UNICODE
6b3d9b83 1170 wcstombs (dll_name_ret, modEntry.szExePath, MAX_PATH + 1);
255e7678 1171#else
6b3d9b83 1172 strcpy (dll_name_ret, modEntry.szExePath);
255e7678 1173#endif
6b3d9b83
PA
1174 found = 1;
1175 break;
1176 }
255e7678 1177
6b3d9b83
PA
1178#ifdef _WIN32_WCE
1179 win32_CloseToolhelp32Snapshot (snapshot_module);
1180#else
255e7678 1181 CloseHandle (snapshot_module);
6b3d9b83
PA
1182#endif
1183 return found;
255e7678
DJ
1184}
1185
1186static void
1187handle_load_dll (void)
1188{
1189 LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
1190 char dll_buf[MAX_PATH + 1];
1191 char *dll_name = NULL;
e8f0053d 1192 CORE_ADDR load_addr;
255e7678
DJ
1193
1194 dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
1195
34d86ddd
PA
1196 /* Windows does not report the image name of the dlls in the debug
1197 event on attaches. We resort to iterating over the list of
1198 loaded dlls looking for a match by image base. */
e8f0053d 1199 if (!psapi_get_dll_name (event->lpBaseOfDll, dll_buf))
34d86ddd
PA
1200 {
1201 if (!server_waiting)
1202 /* On some versions of Windows and Windows CE, we can't create
1203 toolhelp snapshots while the inferior is stopped in a
1204 LOAD_DLL_DEBUG_EVENT due to a dll load, but we can while
1205 Windows is reporting the already loaded dlls. */
e8f0053d 1206 toolhelp_get_dll_name (event->lpBaseOfDll, dll_buf);
34d86ddd 1207 }
255e7678
DJ
1208
1209 dll_name = dll_buf;
1210
1211 if (*dll_name == '\0')
1212 dll_name = get_image_name (current_process_handle,
1213 event->lpImageName, event->fUnicode);
1214 if (!dll_name)
1215 return;
1216
1217 /* The symbols in a dll are offset by 0x1000, which is the
7a9dd1b2 1218 offset from 0 of the first byte in an image - because
255e7678
DJ
1219 of the file header and the section alignment. */
1220
e8f0053d 1221 load_addr = (CORE_ADDR) (uintptr_t) event->lpBaseOfDll + 0x1000;
255e7678
DJ
1222 win32_add_one_solib (dll_name, load_addr);
1223}
1224
1225static void
1226handle_unload_dll (void)
1227{
1228 CORE_ADDR load_addr =
e8f0053d 1229 (CORE_ADDR) (uintptr_t) current_event.u.UnloadDll.lpBaseOfDll;
255e7678
DJ
1230 load_addr += 0x1000;
1231 unloaded_dll (NULL, load_addr);
1232}
1233
34b34921 1234static void
b80864fb
DJ
1235handle_exception (struct target_waitstatus *ourstatus)
1236{
b80864fb
DJ
1237 DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode;
1238
1239 ourstatus->kind = TARGET_WAITKIND_STOPPED;
1240
b80864fb
DJ
1241 switch (code)
1242 {
1243 case EXCEPTION_ACCESS_VIOLATION:
1244 OUTMSG2 (("EXCEPTION_ACCESS_VIOLATION"));
a493e3e2 1245 ourstatus->value.sig = GDB_SIGNAL_SEGV;
b80864fb
DJ
1246 break;
1247 case STATUS_STACK_OVERFLOW:
1248 OUTMSG2 (("STATUS_STACK_OVERFLOW"));
a493e3e2 1249 ourstatus->value.sig = GDB_SIGNAL_SEGV;
b80864fb
DJ
1250 break;
1251 case STATUS_FLOAT_DENORMAL_OPERAND:
1252 OUTMSG2 (("STATUS_FLOAT_DENORMAL_OPERAND"));
a493e3e2 1253 ourstatus->value.sig = GDB_SIGNAL_FPE;
b80864fb
DJ
1254 break;
1255 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1256 OUTMSG2 (("EXCEPTION_ARRAY_BOUNDS_EXCEEDED"));
a493e3e2 1257 ourstatus->value.sig = GDB_SIGNAL_FPE;
b80864fb
DJ
1258 break;
1259 case STATUS_FLOAT_INEXACT_RESULT:
1260 OUTMSG2 (("STATUS_FLOAT_INEXACT_RESULT"));
a493e3e2 1261 ourstatus->value.sig = GDB_SIGNAL_FPE;
b80864fb
DJ
1262 break;
1263 case STATUS_FLOAT_INVALID_OPERATION:
1264 OUTMSG2 (("STATUS_FLOAT_INVALID_OPERATION"));
a493e3e2 1265 ourstatus->value.sig = GDB_SIGNAL_FPE;
b80864fb
DJ
1266 break;
1267 case STATUS_FLOAT_OVERFLOW:
1268 OUTMSG2 (("STATUS_FLOAT_OVERFLOW"));
a493e3e2 1269 ourstatus->value.sig = GDB_SIGNAL_FPE;
b80864fb
DJ
1270 break;
1271 case STATUS_FLOAT_STACK_CHECK:
1272 OUTMSG2 (("STATUS_FLOAT_STACK_CHECK"));
a493e3e2 1273 ourstatus->value.sig = GDB_SIGNAL_FPE;
b80864fb
DJ
1274 break;
1275 case STATUS_FLOAT_UNDERFLOW:
1276 OUTMSG2 (("STATUS_FLOAT_UNDERFLOW"));
a493e3e2 1277 ourstatus->value.sig = GDB_SIGNAL_FPE;
b80864fb
DJ
1278 break;
1279 case STATUS_FLOAT_DIVIDE_BY_ZERO:
1280 OUTMSG2 (("STATUS_FLOAT_DIVIDE_BY_ZERO"));
a493e3e2 1281 ourstatus->value.sig = GDB_SIGNAL_FPE;
b80864fb
DJ
1282 break;
1283 case STATUS_INTEGER_DIVIDE_BY_ZERO:
1284 OUTMSG2 (("STATUS_INTEGER_DIVIDE_BY_ZERO"));
a493e3e2 1285 ourstatus->value.sig = GDB_SIGNAL_FPE;
b80864fb
DJ
1286 break;
1287 case STATUS_INTEGER_OVERFLOW:
1288 OUTMSG2 (("STATUS_INTEGER_OVERFLOW"));
a493e3e2 1289 ourstatus->value.sig = GDB_SIGNAL_FPE;
b80864fb
DJ
1290 break;
1291 case EXCEPTION_BREAKPOINT:
1292 OUTMSG2 (("EXCEPTION_BREAKPOINT"));
a493e3e2 1293 ourstatus->value.sig = GDB_SIGNAL_TRAP;
ed50f18f
PA
1294#ifdef _WIN32_WCE
1295 /* Remove the initial breakpoint. */
1296 check_breakpoints ((CORE_ADDR) (long) current_event
1b3f6016 1297 .u.Exception.ExceptionRecord.ExceptionAddress);
ed50f18f 1298#endif
b80864fb
DJ
1299 break;
1300 case DBG_CONTROL_C:
1301 OUTMSG2 (("DBG_CONTROL_C"));
a493e3e2 1302 ourstatus->value.sig = GDB_SIGNAL_INT;
b80864fb
DJ
1303 break;
1304 case DBG_CONTROL_BREAK:
1305 OUTMSG2 (("DBG_CONTROL_BREAK"));
a493e3e2 1306 ourstatus->value.sig = GDB_SIGNAL_INT;
b80864fb
DJ
1307 break;
1308 case EXCEPTION_SINGLE_STEP:
1309 OUTMSG2 (("EXCEPTION_SINGLE_STEP"));
a493e3e2 1310 ourstatus->value.sig = GDB_SIGNAL_TRAP;
b80864fb
DJ
1311 break;
1312 case EXCEPTION_ILLEGAL_INSTRUCTION:
1313 OUTMSG2 (("EXCEPTION_ILLEGAL_INSTRUCTION"));
a493e3e2 1314 ourstatus->value.sig = GDB_SIGNAL_ILL;
b80864fb
DJ
1315 break;
1316 case EXCEPTION_PRIV_INSTRUCTION:
1317 OUTMSG2 (("EXCEPTION_PRIV_INSTRUCTION"));
a493e3e2 1318 ourstatus->value.sig = GDB_SIGNAL_ILL;
b80864fb
DJ
1319 break;
1320 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
1321 OUTMSG2 (("EXCEPTION_NONCONTINUABLE_EXCEPTION"));
a493e3e2 1322 ourstatus->value.sig = GDB_SIGNAL_ILL;
b80864fb
DJ
1323 break;
1324 default:
1325 if (current_event.u.Exception.dwFirstChance)
34b34921
PA
1326 {
1327 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
1328 return;
1329 }
dfe07582
CV
1330 OUTMSG2 (("gdbserver: unknown target exception 0x%08x at 0x%s",
1331 (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionCode,
1332 phex_nz ((uintptr_t) current_event.u.Exception.ExceptionRecord.
1333 ExceptionAddress, sizeof (uintptr_t))));
a493e3e2 1334 ourstatus->value.sig = GDB_SIGNAL_UNKNOWN;
b80864fb
DJ
1335 break;
1336 }
1337 OUTMSG2 (("\n"));
1338 last_sig = ourstatus->value.sig;
b80864fb
DJ
1339}
1340
4d5d1aaa 1341
34b34921 1342static void
4d5d1aaa
PA
1343suspend_one_thread (struct inferior_list_entry *entry)
1344{
1345 struct thread_info *thread = (struct thread_info *) entry;
1346 win32_thread_info *th = inferior_target_data (thread);
1347
1348 if (!th->suspended)
1349 {
1350 if (SuspendThread (th->h) == (DWORD) -1)
1351 {
1352 DWORD err = GetLastError ();
1353 OUTMSG (("warning: SuspendThread failed in suspend_one_thread, "
1354 "(error %d): %s\n", (int) err, strwinerror (err)));
1355 }
1356 else
1357 th->suspended = 1;
1358 }
1359}
1360
1361static void
1362fake_breakpoint_event (void)
b80864fb 1363{
4d5d1aaa 1364 OUTMSG2(("fake_breakpoint_event\n"));
b80864fb 1365
4d5d1aaa
PA
1366 faked_breakpoint = 1;
1367
1368 memset (&current_event, 0, sizeof (current_event));
1369 current_event.dwThreadId = main_thread_id;
1370 current_event.dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
1371 current_event.u.Exception.ExceptionRecord.ExceptionCode
1372 = EXCEPTION_BREAKPOINT;
1373
1374 for_each_inferior (&all_threads, suspend_one_thread);
1375}
1376
b65d95c5
DJ
1377#ifdef _WIN32_WCE
1378static int
1379auto_delete_breakpoint (CORE_ADDR stop_pc)
1380{
1381 return 1;
1382}
1383#endif
1384
4d5d1aaa
PA
1385/* Get the next event from the child. */
1386
1387static int
1388get_child_debug_event (struct target_waitstatus *ourstatus)
1389{
95954743
PA
1390 ptid_t ptid;
1391
a493e3e2 1392 last_sig = GDB_SIGNAL_0;
b80864fb
DJ
1393 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
1394
4d5d1aaa
PA
1395 /* Check if GDB sent us an interrupt request. */
1396 check_remote_input_interrupt_request ();
1397
1398 if (soft_interrupt_requested)
1399 {
1400 soft_interrupt_requested = 0;
1401 fake_breakpoint_event ();
1402 goto gotevent;
1403 }
1404
d97903b2
PA
1405#ifndef _WIN32_WCE
1406 attaching = 0;
1407#else
1408 if (attaching)
1409 {
1410 /* WinCE doesn't set an initial breakpoint automatically. To
1b3f6016
PA
1411 stop the inferior, we flush all currently pending debug
1412 events -- the thread list and the dll list are always
1413 reported immediatelly without delay, then, we suspend all
1414 threads and pretend we saw a trap at the current PC of the
1415 main thread.
1416
1417 Contrary to desktop Windows, Windows CE *does* report the dll
1418 names on LOAD_DLL_DEBUG_EVENTs resulting from a
1419 DebugActiveProcess call. This limits the way we can detect
1420 if all the dlls have already been reported. If we get a real
1421 debug event before leaving attaching, the worst that will
1422 happen is the user will see a spurious breakpoint. */
d97903b2
PA
1423
1424 current_event.dwDebugEventCode = 0;
1425 if (!WaitForDebugEvent (&current_event, 0))
1b3f6016
PA
1426 {
1427 OUTMSG2(("no attach events left\n"));
1428 fake_breakpoint_event ();
1429 attaching = 0;
1430 }
d97903b2 1431 else
1b3f6016 1432 OUTMSG2(("got attach event\n"));
d97903b2
PA
1433 }
1434 else
1435#endif
1436 {
1437 /* Keep the wait time low enough for confortable remote
1b3f6016
PA
1438 interruption, but high enough so gdbserver doesn't become a
1439 bottleneck. */
d97903b2 1440 if (!WaitForDebugEvent (&current_event, 250))
912cf4ba
PA
1441 {
1442 DWORD e = GetLastError();
1443
1444 if (e == ERROR_PIPE_NOT_CONNECTED)
1445 {
1446 /* This will happen if the loader fails to succesfully
1447 load the application, e.g., if the main executable
1448 tries to pull in a non-existing export from a
1449 DLL. */
1450 ourstatus->kind = TARGET_WAITKIND_EXITED;
1451 ourstatus->value.integer = 1;
1452 return 1;
1453 }
1454
1455 return 0;
1456 }
d97903b2 1457 }
4d5d1aaa
PA
1458
1459 gotevent:
b80864fb 1460
34b34921 1461 switch (current_event.dwDebugEventCode)
b80864fb
DJ
1462 {
1463 case CREATE_THREAD_DEBUG_EVENT:
1464 OUTMSG2 (("gdbserver: kernel event CREATE_THREAD_DEBUG_EVENT "
dfe07582 1465 "for pid=%u tid=%x)\n",
b80864fb
DJ
1466 (unsigned) current_event.dwProcessId,
1467 (unsigned) current_event.dwThreadId));
1468
1469 /* Record the existence of this thread. */
95954743
PA
1470 child_add_thread (current_event.dwProcessId,
1471 current_event.dwThreadId,
711e434b
PM
1472 current_event.u.CreateThread.hThread,
1473 current_event.u.CreateThread.lpThreadLocalBase);
b80864fb
DJ
1474 break;
1475
1476 case EXIT_THREAD_DEBUG_EVENT:
1477 OUTMSG2 (("gdbserver: kernel event EXIT_THREAD_DEBUG_EVENT "
dfe07582 1478 "for pid=%u tid=%x\n",
b80864fb
DJ
1479 (unsigned) current_event.dwProcessId,
1480 (unsigned) current_event.dwThreadId));
95954743
PA
1481 child_delete_thread (current_event.dwProcessId,
1482 current_event.dwThreadId);
aeeb81d1
PA
1483
1484 current_inferior = (struct thread_info *) all_threads.head;
1485 return 1;
b80864fb
DJ
1486
1487 case CREATE_PROCESS_DEBUG_EVENT:
1488 OUTMSG2 (("gdbserver: kernel event CREATE_PROCESS_DEBUG_EVENT "
dfe07582 1489 "for pid=%u tid=%x\n",
b80864fb
DJ
1490 (unsigned) current_event.dwProcessId,
1491 (unsigned) current_event.dwThreadId));
1492 CloseHandle (current_event.u.CreateProcessInfo.hFile);
1493
1494 current_process_handle = current_event.u.CreateProcessInfo.hProcess;
1495 main_thread_id = current_event.dwThreadId;
1496
1497 ourstatus->kind = TARGET_WAITKIND_EXECD;
1498 ourstatus->value.execd_pathname = "Main executable";
1499
1500 /* Add the main thread. */
95954743
PA
1501 child_add_thread (current_event.dwProcessId,
1502 main_thread_id,
711e434b
PM
1503 current_event.u.CreateProcessInfo.hThread,
1504 current_event.u.CreateProcessInfo.lpThreadLocalBase);
b80864fb 1505
95954743 1506 ourstatus->value.related_pid = debug_event_ptid (&current_event);
ed50f18f 1507#ifdef _WIN32_WCE
d97903b2
PA
1508 if (!attaching)
1509 {
1510 /* Windows CE doesn't set the initial breakpoint
1511 automatically like the desktop versions of Windows do.
1512 We add it explicitly here. It will be removed as soon as
1513 it is hit. */
1514 set_breakpoint_at ((CORE_ADDR) (long) current_event.u
1515 .CreateProcessInfo.lpStartAddress,
b65d95c5 1516 auto_delete_breakpoint);
d97903b2 1517 }
ed50f18f 1518#endif
b80864fb
DJ
1519 break;
1520
1521 case EXIT_PROCESS_DEBUG_EVENT:
1522 OUTMSG2 (("gdbserver: kernel event EXIT_PROCESS_DEBUG_EVENT "
dfe07582 1523 "for pid=%u tid=%x\n",
b80864fb
DJ
1524 (unsigned) current_event.dwProcessId,
1525 (unsigned) current_event.dwThreadId));
1526 ourstatus->kind = TARGET_WAITKIND_EXITED;
1527 ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
18aae699 1528 child_continue (DBG_CONTINUE, -1);
b80864fb 1529 CloseHandle (current_process_handle);
9d606399 1530 current_process_handle = NULL;
b80864fb
DJ
1531 break;
1532
1533 case LOAD_DLL_DEBUG_EVENT:
1534 OUTMSG2 (("gdbserver: kernel event LOAD_DLL_DEBUG_EVENT "
dfe07582 1535 "for pid=%u tid=%x\n",
b80864fb
DJ
1536 (unsigned) current_event.dwProcessId,
1537 (unsigned) current_event.dwThreadId));
1538 CloseHandle (current_event.u.LoadDll.hFile);
255e7678 1539 handle_load_dll ();
b80864fb
DJ
1540
1541 ourstatus->kind = TARGET_WAITKIND_LOADED;
a493e3e2 1542 ourstatus->value.sig = GDB_SIGNAL_TRAP;
b80864fb
DJ
1543 break;
1544
1545 case UNLOAD_DLL_DEBUG_EVENT:
1546 OUTMSG2 (("gdbserver: kernel event UNLOAD_DLL_DEBUG_EVENT "
dfe07582 1547 "for pid=%u tid=%x\n",
b80864fb
DJ
1548 (unsigned) current_event.dwProcessId,
1549 (unsigned) current_event.dwThreadId));
255e7678
DJ
1550 handle_unload_dll ();
1551 ourstatus->kind = TARGET_WAITKIND_LOADED;
a493e3e2 1552 ourstatus->value.sig = GDB_SIGNAL_TRAP;
b80864fb
DJ
1553 break;
1554
1555 case EXCEPTION_DEBUG_EVENT:
1556 OUTMSG2 (("gdbserver: kernel event EXCEPTION_DEBUG_EVENT "
dfe07582 1557 "for pid=%u tid=%x\n",
b80864fb
DJ
1558 (unsigned) current_event.dwProcessId,
1559 (unsigned) current_event.dwThreadId));
34b34921 1560 handle_exception (ourstatus);
b80864fb
DJ
1561 break;
1562
1563 case OUTPUT_DEBUG_STRING_EVENT:
1564 /* A message from the kernel (or Cygwin). */
1565 OUTMSG2 (("gdbserver: kernel event OUTPUT_DEBUG_STRING_EVENT "
dfe07582 1566 "for pid=%u tid=%x\n",
b80864fb
DJ
1567 (unsigned) current_event.dwProcessId,
1568 (unsigned) current_event.dwThreadId));
bce7165d 1569 handle_output_debug_string (ourstatus);
b80864fb
DJ
1570 break;
1571
1572 default:
1573 OUTMSG2 (("gdbserver: kernel event unknown "
dfe07582 1574 "for pid=%u tid=%x code=%x\n",
b80864fb
DJ
1575 (unsigned) current_event.dwProcessId,
1576 (unsigned) current_event.dwThreadId,
dfe07582 1577 (unsigned) current_event.dwDebugEventCode));
b80864fb
DJ
1578 break;
1579 }
1580
aeeb81d1 1581 ptid = debug_event_ptid (&current_event);
b80864fb 1582 current_inferior =
95954743 1583 (struct thread_info *) find_inferior_id (&all_threads, ptid);
4d5d1aaa 1584 return 1;
b80864fb
DJ
1585}
1586
1587/* Wait for the inferior process to change state.
1588 STATUS will be filled in with a response code to send to GDB.
1589 Returns the signal which caused the process to stop. */
95954743
PA
1590static ptid_t
1591win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
b80864fb 1592{
442ea881 1593 struct regcache *regcache;
95954743 1594
b80864fb
DJ
1595 while (1)
1596 {
5b1c542e 1597 if (!get_child_debug_event (ourstatus))
4d5d1aaa 1598 continue;
b80864fb 1599
5b1c542e 1600 switch (ourstatus->kind)
b80864fb 1601 {
34b34921 1602 case TARGET_WAITKIND_EXITED:
b80864fb 1603 OUTMSG2 (("Child exited with retcode = %x\n",
5b1c542e 1604 ourstatus->value.integer));
5ac588cf 1605 win32_clear_inferiors ();
95954743 1606 return pid_to_ptid (current_event.dwProcessId);
34b34921 1607 case TARGET_WAITKIND_STOPPED:
1b3f6016 1608 case TARGET_WAITKIND_LOADED:
f72f3e60 1609 OUTMSG2 (("Child Stopped with signal = %d \n",
10357975 1610 ourstatus->value.sig));
b80864fb 1611
442ea881
PA
1612 regcache = get_thread_regcache (current_inferior, 1);
1613 child_fetch_inferior_registers (regcache, -1);
b80864fb 1614
5b1c542e 1615 if (ourstatus->kind == TARGET_WAITKIND_LOADED
255e7678
DJ
1616 && !server_waiting)
1617 {
1618 /* When gdb connects, we want to be stopped at the
1619 initial breakpoint, not in some dll load event. */
1620 child_continue (DBG_CONTINUE, -1);
1621 break;
1622 }
1623
5b1c542e
PA
1624 /* We don't expose _LOADED events to gdbserver core. See
1625 the `dlls_changed' global. */
1626 if (ourstatus->kind == TARGET_WAITKIND_LOADED)
1627 ourstatus->kind = TARGET_WAITKIND_STOPPED;
1628
95954743 1629 return debug_event_ptid (&current_event);
1b3f6016 1630 default:
5b1c542e 1631 OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind));
1b3f6016
PA
1632 /* fall-through */
1633 case TARGET_WAITKIND_SPURIOUS:
1634 case TARGET_WAITKIND_EXECD:
34b34921
PA
1635 /* do nothing, just continue */
1636 child_continue (DBG_CONTINUE, -1);
1637 break;
b80864fb 1638 }
b80864fb
DJ
1639 }
1640}
1641
1642/* Fetch registers from the inferior process.
1643 If REGNO is -1, fetch all registers; otherwise, fetch at least REGNO. */
1644static void
442ea881 1645win32_fetch_inferior_registers (struct regcache *regcache, int regno)
b80864fb 1646{
442ea881 1647 child_fetch_inferior_registers (regcache, regno);
b80864fb
DJ
1648}
1649
1650/* Store registers to the inferior process.
1651 If REGNO is -1, store all registers; otherwise, store at least REGNO. */
1652static void
442ea881 1653win32_store_inferior_registers (struct regcache *regcache, int regno)
b80864fb 1654{
442ea881 1655 child_store_inferior_registers (regcache, regno);
b80864fb
DJ
1656}
1657
1658/* Read memory from the inferior process. This should generally be
1659 called through read_inferior_memory, which handles breakpoint shadowing.
1660 Read LEN bytes at MEMADDR into a buffer at MYADDR. */
1661static int
1662win32_read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
1663{
ed50f18f 1664 return child_xfer_memory (memaddr, (char *) myaddr, len, 0, 0) != len;
b80864fb
DJ
1665}
1666
1667/* Write memory to the inferior process. This should generally be
1668 called through write_inferior_memory, which handles breakpoint shadowing.
1669 Write LEN bytes from the buffer at MYADDR to MEMADDR.
1670 Returns 0 on success and errno on failure. */
1671static int
1672win32_write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr,
1673 int len)
1674{
1675 return child_xfer_memory (memaddr, (char *) myaddr, len, 1, 0) != len;
1676}
1677
7390519e
PA
1678/* Send an interrupt request to the inferior process. */
1679static void
1680win32_request_interrupt (void)
1681{
1682 winapi_DebugBreakProcess DebugBreakProcess;
1683 winapi_GenerateConsoleCtrlEvent GenerateConsoleCtrlEvent;
1684
1685#ifdef _WIN32_WCE
1686 HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
1687#else
1688 HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
1689#endif
1690
1691 GenerateConsoleCtrlEvent = GETPROCADDRESS (dll, GenerateConsoleCtrlEvent);
1692
1693 if (GenerateConsoleCtrlEvent != NULL
1694 && GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, current_process_id))
1695 return;
1696
1697 /* GenerateConsoleCtrlEvent can fail if process id being debugged is
1698 not a process group id.
1699 Fallback to XP/Vista 'DebugBreakProcess', which generates a
1700 breakpoint exception in the interior process. */
1701
1702 DebugBreakProcess = GETPROCADDRESS (dll, DebugBreakProcess);
1703
1704 if (DebugBreakProcess != NULL
1705 && DebugBreakProcess (current_process_handle))
1706 return;
1707
4d5d1aaa
PA
1708 /* Last resort, suspend all threads manually. */
1709 soft_interrupt_requested = 1;
7390519e
PA
1710}
1711
59a016f0
PA
1712#ifdef _WIN32_WCE
1713int
1714win32_error_to_fileio_error (DWORD err)
1715{
1716 switch (err)
1717 {
1718 case ERROR_BAD_PATHNAME:
1719 case ERROR_FILE_NOT_FOUND:
1720 case ERROR_INVALID_NAME:
1721 case ERROR_PATH_NOT_FOUND:
1722 return FILEIO_ENOENT;
1723 case ERROR_CRC:
1724 case ERROR_IO_DEVICE:
1725 case ERROR_OPEN_FAILED:
1726 return FILEIO_EIO;
1727 case ERROR_INVALID_HANDLE:
1728 return FILEIO_EBADF;
1729 case ERROR_ACCESS_DENIED:
1730 case ERROR_SHARING_VIOLATION:
1731 return FILEIO_EACCES;
1732 case ERROR_NOACCESS:
1733 return FILEIO_EFAULT;
1734 case ERROR_BUSY:
1735 return FILEIO_EBUSY;
1736 case ERROR_ALREADY_EXISTS:
1737 case ERROR_FILE_EXISTS:
1738 return FILEIO_EEXIST;
1739 case ERROR_BAD_DEVICE:
1740 return FILEIO_ENODEV;
1741 case ERROR_DIRECTORY:
1742 return FILEIO_ENOTDIR;
1743 case ERROR_FILENAME_EXCED_RANGE:
1744 case ERROR_INVALID_DATA:
1745 case ERROR_INVALID_PARAMETER:
1746 case ERROR_NEGATIVE_SEEK:
1747 return FILEIO_EINVAL;
1748 case ERROR_TOO_MANY_OPEN_FILES:
1749 return FILEIO_EMFILE;
1750 case ERROR_HANDLE_DISK_FULL:
1751 case ERROR_DISK_FULL:
1752 return FILEIO_ENOSPC;
1753 case ERROR_WRITE_PROTECT:
1754 return FILEIO_EROFS;
1755 case ERROR_NOT_SUPPORTED:
1756 return FILEIO_ENOSYS;
1757 }
1758
1759 return FILEIO_EUNKNOWN;
1760}
1761
1762static void
1763wince_hostio_last_error (char *buf)
1764{
1765 DWORD winerr = GetLastError ();
1766 int fileio_err = win32_error_to_fileio_error (winerr);
1767 sprintf (buf, "F-1,%x", fileio_err);
1768}
1769#endif
1770
711e434b
PM
1771/* Write Windows OS Thread Information Block address. */
1772
1773static int
1774win32_get_tib_address (ptid_t ptid, CORE_ADDR *addr)
1775{
1776 win32_thread_info *th;
1777 th = thread_rec (ptid, 0);
1778 if (th == NULL)
1779 return 0;
1780 if (addr != NULL)
1781 *addr = th->thread_local_base;
1782 return 1;
1783}
1784
b80864fb
DJ
1785static struct target_ops win32_target_ops = {
1786 win32_create_inferior,
1787 win32_attach,
1788 win32_kill,
1789 win32_detach,
505106cd 1790 win32_mourn,
444d6139 1791 win32_join,
b80864fb
DJ
1792 win32_thread_alive,
1793 win32_resume,
1794 win32_wait,
1795 win32_fetch_inferior_registers,
1796 win32_store_inferior_registers,
90d74c30 1797 NULL, /* prepare_to_access_memory */
0146f85b 1798 NULL, /* done_accessing_memory */
b80864fb
DJ
1799 win32_read_inferior_memory,
1800 win32_write_inferior_memory,
711e434b 1801 NULL, /* lookup_symbols */
7390519e 1802 win32_request_interrupt,
711e434b 1803 NULL, /* read_auxv */
aa5ca48f
DE
1804 win32_insert_point,
1805 win32_remove_point,
1806 win32_stopped_by_watchpoint,
1807 win32_stopped_data_address,
711e434b
PM
1808 NULL, /* read_offsets */
1809 NULL, /* get_tls_address */
1810 NULL, /* qxfer_spu */
59a016f0
PA
1811#ifdef _WIN32_WCE
1812 wince_hostio_last_error,
1813#else
1814 hostio_last_error_from_errno,
1815#endif
711e434b
PM
1816 NULL, /* qxfer_osdata */
1817 NULL, /* qxfer_siginfo */
1818 NULL, /* supports_non_stop */
1819 NULL, /* async */
1820 NULL, /* start_non_stop */
1821 NULL, /* supports_multi_process */
1822 NULL, /* handle_monitor_command */
1823 NULL, /* core_of_thread */
881127c9 1824 NULL, /* read_loadmap */
711e434b
PM
1825 NULL, /* process_qsupported */
1826 NULL, /* supports_tracepoints */
1827 NULL, /* read_pc */
1828 NULL, /* write_pc */
1829 NULL, /* thread_stopped */
7984d532 1830 win32_get_tib_address
b80864fb
DJ
1831};
1832
1833/* Initialize the Win32 backend. */
1834void
1835initialize_low (void)
1836{
1837 set_target_ops (&win32_target_ops);
ed50f18f
PA
1838 if (the_low_target.breakpoint != NULL)
1839 set_breakpoint_data (the_low_target.breakpoint,
1840 the_low_target.breakpoint_len);
d05b4ac3 1841 the_low_target.arch_setup ();
b80864fb 1842}