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