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