]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/gdbserver/win32-low.c
* MAINTAINERS: Move Fred Fish to Past Maintainers.
[thirdparty/binutils-gdb.git] / gdb / gdbserver / win32-low.c
CommitLineData
b80864fb 1/* Low level interface to Windows debugging, for gdbserver.
6aba47ca 2 Copyright (C) 2006, 2007 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"
ed50f18f
PA
24#include "mem-break.h"
25#include "win32-low.h"
b80864fb
DJ
26
27#include <windows.h>
ed50f18f 28#include <winnt.h>
b80864fb 29#include <imagehlp.h>
255e7678 30#include <tlhelp32.h>
b80864fb
DJ
31#include <psapi.h>
32#include <sys/param.h>
33#include <malloc.h>
34#include <process.h>
35
36#ifndef USE_WIN32API
37#include <sys/cygwin.h>
38#endif
39
40#define LOG 0
41
42#define OUTMSG(X) do { printf X; fflush (stdout); } while (0)
43#if LOG
44#define OUTMSG2(X) do { printf X; fflush (stdout); } while (0)
45#else
ed50f18f
PA
46#define OUTMSG2(X) do ; while (0)
47#endif
48
49#ifndef _T
50#define _T(x) TEXT (x)
51#endif
52
53#ifndef COUNTOF
54#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0]))
b80864fb
DJ
55#endif
56
bf914831
PA
57#ifdef _WIN32_WCE
58# define GETPROCADDRESS(DLL, PROC) \
59 ((winapi_ ## PROC) GetProcAddress (DLL, TEXT (#PROC)))
60#else
61# define GETPROCADDRESS(DLL, PROC) \
62 ((winapi_ ## PROC) GetProcAddress (DLL, #PROC))
63#endif
64
b80864fb
DJ
65int using_threads = 1;
66
67/* Globals. */
68static HANDLE current_process_handle = NULL;
69static DWORD current_process_id = 0;
70static enum target_signal last_sig = TARGET_SIGNAL_0;
71
72/* The current debug event from WaitForDebugEvent. */
73static DEBUG_EVENT current_event;
74
ed50f18f 75#define NUM_REGS (the_low_target.num_regs)
b80864fb 76
bf914831
PA
77typedef BOOL WINAPI (*winapi_DebugActiveProcessStop) (DWORD dwProcessId);
78typedef BOOL WINAPI (*winapi_DebugSetProcessKillOnExit) (BOOL KillOnExit);
7390519e
PA
79typedef BOOL WINAPI (*winapi_DebugBreakProcess) (HANDLE);
80typedef BOOL WINAPI (*winapi_GenerateConsoleCtrlEvent) (DWORD, DWORD);
b80864fb 81
b80864fb
DJ
82static DWORD main_thread_id = 0;
83
34b34921
PA
84static void win32_resume (struct thread_resume *resume_info);
85
b80864fb
DJ
86/* Get the thread ID from the current selected inferior (the current
87 thread). */
88static DWORD
89current_inferior_tid (void)
90{
41093d81 91 win32_thread_info *th = inferior_target_data (current_inferior);
b80864fb
DJ
92 return th->tid;
93}
94
95/* Find a thread record given a thread id. If GET_CONTEXT is set then
96 also retrieve the context for this thread. */
41093d81 97static win32_thread_info *
b80864fb
DJ
98thread_rec (DWORD id, int get_context)
99{
100 struct thread_info *thread;
41093d81 101 win32_thread_info *th;
b80864fb
DJ
102
103 thread = (struct thread_info *) find_inferior_id (&all_threads, id);
104 if (thread == NULL)
105 return NULL;
106
107 th = inferior_target_data (thread);
108 if (!th->suspend_count && get_context)
109 {
34b34921 110 if (id != current_event.dwThreadId)
b80864fb 111 th->suspend_count = SuspendThread (th->h) + 1;
b80864fb 112
34b34921 113 (*the_low_target.get_thread_context) (th, &current_event);
b80864fb
DJ
114 }
115
116 return th;
117}
118
119/* Add a thread to the thread list. */
41093d81 120static win32_thread_info *
b80864fb
DJ
121child_add_thread (DWORD tid, HANDLE h)
122{
41093d81 123 win32_thread_info *th;
b80864fb
DJ
124
125 if ((th = thread_rec (tid, FALSE)))
126 return th;
127
41093d81 128 th = (win32_thread_info *) malloc (sizeof (*th));
b80864fb
DJ
129 memset (th, 0, sizeof (*th));
130 th->tid = tid;
131 th->h = h;
132
133 add_thread (tid, th, (unsigned int) tid);
134 set_inferior_regcache_data ((struct thread_info *)
135 find_inferior_id (&all_threads, tid),
136 new_register_cache ());
137
34b34921
PA
138 if (the_low_target.thread_added != NULL)
139 (*the_low_target.thread_added) (th);
b80864fb
DJ
140
141 return th;
142}
143
144/* Delete a thread from the list of threads. */
145static void
146delete_thread_info (struct inferior_list_entry *thread)
147{
41093d81 148 win32_thread_info *th = inferior_target_data ((struct thread_info *) thread);
b80864fb
DJ
149
150 remove_thread ((struct thread_info *) thread);
151 CloseHandle (th->h);
152 free (th);
153}
154
155/* Delete a thread from the list of threads. */
156static void
157child_delete_thread (DWORD id)
158{
159 struct inferior_list_entry *thread;
160
161 /* If the last thread is exiting, just return. */
162 if (all_threads.head == all_threads.tail)
163 return;
164
165 thread = find_inferior_id (&all_threads, id);
166 if (thread == NULL)
167 return;
168
169 delete_thread_info (thread);
170}
171
172/* Transfer memory from/to the debugged process. */
173static int
174child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
175 int write, struct target_ops *target)
176{
177 SIZE_T done;
178 long addr = (long) memaddr;
179
180 if (write)
181 {
182 WriteProcessMemory (current_process_handle, (LPVOID) addr,
183 (LPCVOID) our, len, &done);
184 FlushInstructionCache (current_process_handle, (LPCVOID) addr, len);
185 }
186 else
187 {
188 ReadProcessMemory (current_process_handle, (LPCVOID) addr, (LPVOID) our,
189 len, &done);
190 }
191 return done;
192}
193
194/* Generally, what has the program done? */
195enum target_waitkind
196{
197 /* The program has exited. The exit status is in value.integer. */
198 TARGET_WAITKIND_EXITED,
199
200 /* The program has stopped with a signal. Which signal is in
201 value.sig. */
202 TARGET_WAITKIND_STOPPED,
203
255e7678
DJ
204 /* The program is letting us know that it dynamically loaded
205 or unloaded something. */
b80864fb
DJ
206 TARGET_WAITKIND_LOADED,
207
208 /* The program has exec'ed a new executable file. The new file's
209 pathname is pointed to by value.execd_pathname. */
b80864fb
DJ
210 TARGET_WAITKIND_EXECD,
211
7390519e
PA
212 /* Nothing interesting happened, but we stopped anyway. We take the
213 chance to check if GDB requested an interrupt. */
b80864fb
DJ
214 TARGET_WAITKIND_SPURIOUS,
215};
216
217struct target_waitstatus
218{
219 enum target_waitkind kind;
220
221 /* Forked child pid, execd pathname, exit status or signal number. */
222 union
223 {
224 int integer;
225 enum target_signal sig;
226 int related_pid;
227 char *execd_pathname;
228 int syscall_id;
229 }
230 value;
231};
232
ed50f18f 233/* Clear out any old thread list and reinitialize it to a pristine
b80864fb
DJ
234 state. */
235static void
236child_init_thread_list (void)
237{
238 for_each_inferior (&all_threads, delete_thread_info);
239}
240
241static void
242do_initial_child_stuff (DWORD pid)
243{
b80864fb
DJ
244 last_sig = TARGET_SIGNAL_0;
245
b80864fb
DJ
246 memset (&current_event, 0, sizeof (current_event));
247
248 child_init_thread_list ();
ed50f18f
PA
249
250 if (the_low_target.initial_stuff != NULL)
251 (*the_low_target.initial_stuff) ();
b80864fb
DJ
252}
253
254/* Resume all artificially suspended threads if we are continuing
255 execution. */
256static int
257continue_one_thread (struct inferior_list_entry *this_thread, void *id_ptr)
258{
259 struct thread_info *thread = (struct thread_info *) this_thread;
260 int thread_id = * (int *) id_ptr;
41093d81 261 win32_thread_info *th = inferior_target_data (thread);
b80864fb
DJ
262 int i;
263
264 if ((thread_id == -1 || thread_id == th->tid)
265 && th->suspend_count)
266 {
34b34921 267 if (th->context.ContextFlags)
b80864fb 268 {
34b34921 269 (*the_low_target.set_thread_context) (th, &current_event);
b80864fb
DJ
270 th->context.ContextFlags = 0;
271 }
34b34921
PA
272
273 for (i = 0; i < th->suspend_count; i++)
274 (void) ResumeThread (th->h);
275 th->suspend_count = 0;
b80864fb
DJ
276 }
277
278 return 0;
279}
280
281static BOOL
282child_continue (DWORD continue_status, int thread_id)
283{
284 BOOL res;
285
286 res = ContinueDebugEvent (current_event.dwProcessId,
287 current_event.dwThreadId, continue_status);
b80864fb
DJ
288 if (res)
289 find_inferior (&all_threads, continue_one_thread, &thread_id);
290
b80864fb
DJ
291 return res;
292}
293
b80864fb
DJ
294/* Fetch register(s) from the current thread context. */
295static void
296child_fetch_inferior_registers (int r)
297{
298 int regno;
41093d81 299 win32_thread_info *th = thread_rec (current_inferior_tid (), TRUE);
b80864fb
DJ
300 if (r == -1 || r == 0 || r > NUM_REGS)
301 child_fetch_inferior_registers (NUM_REGS);
302 else
303 for (regno = 0; regno < r; regno++)
34b34921 304 (*the_low_target.fetch_inferior_register) (th, regno);
b80864fb
DJ
305}
306
307/* Store a new register value into the current thread context. We don't
308 change the program's context until later, when we resume it. */
309static void
310child_store_inferior_registers (int r)
311{
312 int regno;
41093d81 313 win32_thread_info *th = thread_rec (current_inferior_tid (), TRUE);
b80864fb
DJ
314 if (r == -1 || r == 0 || r > NUM_REGS)
315 child_store_inferior_registers (NUM_REGS);
316 else
317 for (regno = 0; regno < r; regno++)
34b34921 318 (*the_low_target.store_inferior_register) (th, regno);
b80864fb
DJ
319}
320
ed50f18f
PA
321/* Map the Windows error number in ERROR to a locale-dependent error
322 message string and return a pointer to it. Typically, the values
323 for ERROR come from GetLastError.
324
325 The string pointed to shall not be modified by the application,
326 but may be overwritten by a subsequent call to strwinerror
327
328 The strwinerror function does not change the current setting
329 of GetLastError. */
330
331char *
332strwinerror (DWORD error)
333{
334 static char buf[1024];
335 TCHAR *msgbuf;
336 DWORD lasterr = GetLastError ();
337 DWORD chars = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
338 | FORMAT_MESSAGE_ALLOCATE_BUFFER,
339 NULL,
340 error,
341 0, /* Default language */
342 (LPVOID)&msgbuf,
343 0,
344 NULL);
345 if (chars != 0)
346 {
347 /* If there is an \r\n appended, zap it. */
348 if (chars >= 2
349 && msgbuf[chars - 2] == '\r'
350 && msgbuf[chars - 1] == '\n')
351 {
352 chars -= 2;
353 msgbuf[chars] = 0;
354 }
355
356 if (chars > ((COUNTOF (buf)) - 1))
357 {
358 chars = COUNTOF (buf) - 1;
359 msgbuf [chars] = 0;
360 }
361
362#ifdef UNICODE
363 wcstombs (buf, msgbuf, chars + 1);
364#else
365 strncpy (buf, msgbuf, chars + 1);
366#endif
367 LocalFree (msgbuf);
368 }
369 else
370 sprintf (buf, "unknown win32 error (%ld)", error);
371
372 SetLastError (lasterr);
373 return buf;
374}
375
b80864fb
DJ
376/* Start a new process.
377 PROGRAM is a path to the program to execute.
378 ARGS is a standard NULL-terminated array of arguments,
379 to be passed to the inferior as ``argv''.
380 Returns the new PID on success, -1 on failure. Registers the new
381 process with the process list. */
382static int
383win32_create_inferior (char *program, char **program_args)
384{
385#ifndef USE_WIN32API
386 char real_path[MAXPATHLEN];
387 char *orig_path, *new_path, *path_ptr;
388#endif
b80864fb
DJ
389 BOOL ret;
390 DWORD flags;
391 char *args;
392 int argslen;
393 int argc;
ed50f18f
PA
394 PROCESS_INFORMATION pi;
395#ifndef __MINGW32CE__
bf914831 396 STARTUPINFOA si = { sizeof (STARTUPINFOA) };
ed50f18f
PA
397 char *winenv = NULL;
398#else
399 wchar_t *wargs, *wprogram;
400#endif
b80864fb
DJ
401
402 if (!program)
403 error ("No executable specified, specify executable to debug.\n");
404
b80864fb
DJ
405 flags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
406
407#ifndef USE_WIN32API
408 orig_path = NULL;
409 path_ptr = getenv ("PATH");
410 if (path_ptr)
411 {
412 orig_path = alloca (strlen (path_ptr) + 1);
413 new_path = alloca (cygwin_posix_to_win32_path_list_buf_size (path_ptr));
414 strcpy (orig_path, path_ptr);
415 cygwin_posix_to_win32_path_list (path_ptr, new_path);
416 setenv ("PATH", new_path, 1);
417 }
418 cygwin_conv_to_win32_path (program, real_path);
419 program = real_path;
420#endif
421
ed50f18f 422 argslen = 1;
b80864fb
DJ
423 for (argc = 1; program_args[argc]; argc++)
424 argslen += strlen (program_args[argc]) + 1;
425 args = alloca (argslen);
ed50f18f 426 args[0] = '\0';
b80864fb
DJ
427 for (argc = 1; program_args[argc]; argc++)
428 {
429 /* FIXME: Can we do better about quoting? How does Cygwin
430 handle this? */
431 strcat (args, " ");
432 strcat (args, program_args[argc]);
433 }
ed50f18f 434 OUTMSG2 (("Command line is \"%s\"\n", args));
b80864fb 435
ed50f18f 436#ifdef CREATE_NEW_PROCESS_GROUP
b80864fb 437 flags |= CREATE_NEW_PROCESS_GROUP;
ed50f18f 438#endif
b80864fb 439
ed50f18f
PA
440#ifdef __MINGW32CE__
441 to_back_slashes (program);
442 wargs = alloca (argslen * sizeof (wchar_t));
443 mbstowcs (wargs, args, argslen);
444 wprogram = alloca ((strlen (program) + 1) * sizeof (wchar_t));
445 mbstowcs (wprogram, program, strlen (program) + 1);
446 ret = CreateProcessW (wprogram, /* image name */
447 wargs, /* command line */
448 NULL, /* security, not supported */
449 NULL, /* thread, not supported */
450 FALSE, /* inherit handles, not supported */
451 flags, /* start flags */
452 NULL, /* environment, not supported */
453 NULL, /* current directory, not supported */
454 NULL, /* start info, not supported */
455 &pi); /* proc info */
456#else
bf914831
PA
457 ret = CreateProcessA (program, /* image name */
458 args, /* command line */
459 NULL, /* security */
460 NULL, /* thread */
461 TRUE, /* inherit handles */
462 flags, /* start flags */
463 winenv, /* environment */
464 NULL, /* current directory */
465 &si, /* start info */
466 &pi); /* proc info */
ed50f18f 467#endif
b80864fb
DJ
468
469#ifndef USE_WIN32API
470 if (orig_path)
471 setenv ("PATH", orig_path, 1);
472#endif
473
474 if (!ret)
475 {
ed50f18f
PA
476 DWORD err = GetLastError ();
477 error ("Error creating process \"%s%s\", (error %d): %s\n",
478 program, args, (int) err, strwinerror (err));
b80864fb
DJ
479 }
480 else
481 {
482 OUTMSG2 (("Process created: %s\n", (char *) args));
483 }
484
ed50f18f
PA
485#ifndef _WIN32_WCE
486 /* On Windows CE this handle can't be closed. The OS reuses
487 it in the debug events, while the 9x/NT versions of Windows
488 probably use a DuplicateHandle'd one. */
b80864fb 489 CloseHandle (pi.hThread);
ed50f18f 490#endif
b80864fb
DJ
491
492 current_process_handle = pi.hProcess;
493 current_process_id = pi.dwProcessId;
494
495 do_initial_child_stuff (current_process_id);
496
497 return current_process_id;
498}
499
500/* Attach to a running process.
501 PID is the process ID to attach to, specified by the user
502 or a higher layer. */
503static int
504win32_attach (unsigned long pid)
505{
bf914831
PA
506 winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL;
507 winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
ed50f18f
PA
508#ifdef _WIN32_WCE
509 HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
510#else
511 HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
512#endif
bf914831
PA
513 DebugActiveProcessStop = GETPROCADDRESS (dll, DebugActiveProcessStop);
514 DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit);
b80864fb 515
1d5315fe
PA
516 if (DebugActiveProcess (pid))
517 {
518 if (DebugSetProcessKillOnExit != NULL)
519 DebugSetProcessKillOnExit (FALSE);
b80864fb 520
1d5315fe 521 current_process_handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
b80864fb 522
1d5315fe
PA
523 if (current_process_handle != NULL)
524 {
525 current_process_id = pid;
526 do_initial_child_stuff (pid);
527 return 0;
528 }
b80864fb
DJ
529 if (DebugActiveProcessStop != NULL)
530 DebugActiveProcessStop (current_process_id);
531 }
532
1d5315fe 533 error ("Attach to process failed.");
b80864fb
DJ
534}
535
bce7165d
PA
536/* Handle OUTPUT_DEBUG_STRING_EVENT from child process. */
537static void
538handle_output_debug_string (struct target_waitstatus *ourstatus)
539{
540#define READ_BUFFER_LEN 1024
541 CORE_ADDR addr;
542 char s[READ_BUFFER_LEN + 1] = { 0 };
543 DWORD nbytes = current_event.u.DebugString.nDebugStringLength;
544
545 if (nbytes == 0)
546 return;
547
548 if (nbytes > READ_BUFFER_LEN)
549 nbytes = READ_BUFFER_LEN;
550
551 addr = (CORE_ADDR) (size_t) current_event.u.DebugString.lpDebugStringData;
552
553 if (current_event.u.DebugString.fUnicode)
554 {
555 /* The event tells us how many bytes, not chars, even
556 in Unicode. */
557 WCHAR buffer[(READ_BUFFER_LEN + 1) / sizeof (WCHAR)] = { 0 };
558 if (read_inferior_memory (addr, (unsigned char *) buffer, nbytes) != 0)
559 return;
560 wcstombs (s, buffer, (nbytes + 1) / sizeof (WCHAR));
561 }
562 else
563 {
564 if (read_inferior_memory (addr, (unsigned char *) s, nbytes) != 0)
565 return;
566 }
567
568 if (strncmp (s, "cYg", 3) != 0)
45e2715e
PA
569 {
570 if (!server_waiting)
571 {
572 OUTMSG2(("%s", s));
573 return;
574 }
575
576 monitor_output (s);
577 }
bce7165d
PA
578#undef READ_BUFFER_LEN
579}
580
b80864fb
DJ
581/* Kill all inferiors. */
582static void
583win32_kill (void)
584{
ed50f18f
PA
585 win32_thread_info *current_thread;
586
9d606399
DJ
587 if (current_process_handle == NULL)
588 return;
589
b80864fb
DJ
590 TerminateProcess (current_process_handle, 0);
591 for (;;)
592 {
593 if (!child_continue (DBG_CONTINUE, -1))
594 break;
595 if (!WaitForDebugEvent (&current_event, INFINITE))
596 break;
597 if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
598 break;
bce7165d
PA
599 else if (current_event.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT)
600 {
601 struct target_waitstatus our_status = { 0 };
602 handle_output_debug_string (&our_status);
603 }
b80864fb 604 }
ed50f18f
PA
605
606 CloseHandle (current_process_handle);
607
608 current_thread = inferior_target_data (current_inferior);
609 if (current_thread && current_thread->h)
610 {
611 /* This may fail in an attached process, so don't check. */
612 (void) CloseHandle (current_thread->h);
613 }
b80864fb
DJ
614}
615
616/* Detach from all inferiors. */
444d6139 617static int
b80864fb
DJ
618win32_detach (void)
619{
444d6139
PA
620 HANDLE h;
621
bf914831
PA
622 winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL;
623 winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
ed50f18f
PA
624#ifdef _WIN32_WCE
625 HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
626#else
627 HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
628#endif
bf914831
PA
629 DebugActiveProcessStop = GETPROCADDRESS (dll, DebugActiveProcessStop);
630 DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit);
b80864fb 631
444d6139
PA
632 if (DebugSetProcessKillOnExit == NULL
633 || DebugActiveProcessStop == NULL)
634 return -1;
b80864fb 635
444d6139
PA
636 /* We need a new handle, since DebugActiveProcessStop
637 closes all the ones that came through the events. */
638 if ((h = OpenProcess (PROCESS_ALL_ACCESS,
639 FALSE,
640 current_process_id)) == NULL)
641 {
642 /* The process died. */
643 return -1;
644 }
645
646 {
647 struct thread_resume resume;
648 resume.thread = -1;
649 resume.step = 0;
650 resume.sig = 0;
651 resume.leave_stopped = 0;
652 win32_resume (&resume);
653 }
654
655 if (!DebugActiveProcessStop (current_process_id))
656 {
657 CloseHandle (h);
658 return -1;
659 }
660 DebugSetProcessKillOnExit (FALSE);
661
662 current_process_handle = h;
663 return 0;
664}
665
666/* Wait for inferiors to end. */
667static void
668win32_join (void)
669{
670 if (current_process_id == 0
671 || current_process_handle == NULL)
672 return;
673
674 WaitForSingleObject (current_process_handle, INFINITE);
675 CloseHandle (current_process_handle);
676
677 current_process_handle = NULL;
678 current_process_id = 0;
b80864fb
DJ
679}
680
681/* Return 1 iff the thread with thread ID TID is alive. */
682static int
683win32_thread_alive (unsigned long tid)
684{
685 int res;
686
687 /* Our thread list is reliable; don't bother to poll target
688 threads. */
689 if (find_inferior_id (&all_threads, tid) != NULL)
690 res = 1;
691 else
692 res = 0;
693 return res;
694}
695
696/* Resume the inferior process. RESUME_INFO describes how we want
697 to resume. */
698static void
699win32_resume (struct thread_resume *resume_info)
700{
701 DWORD tid;
702 enum target_signal sig;
703 int step;
41093d81 704 win32_thread_info *th;
b80864fb
DJ
705 DWORD continue_status = DBG_CONTINUE;
706
707 /* This handles the very limited set of resume packets that GDB can
708 currently produce. */
709
710 if (resume_info[0].thread == -1)
711 tid = -1;
712 else if (resume_info[1].thread == -1 && !resume_info[1].leave_stopped)
713 tid = -1;
714 else
715 /* Yes, we're ignoring resume_info[0].thread. It'd be tricky to make
716 the Windows resume code do the right thing for thread switching. */
717 tid = current_event.dwThreadId;
718
719 if (resume_info[0].thread != -1)
720 {
721 sig = resume_info[0].sig;
722 step = resume_info[0].step;
723 }
724 else
725 {
726 sig = 0;
727 step = 0;
728 }
729
730 if (sig != TARGET_SIGNAL_0)
731 {
732 if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
733 {
734 OUTMSG (("Cannot continue with signal %d here.\n", sig));
735 }
736 else if (sig == last_sig)
737 continue_status = DBG_EXCEPTION_NOT_HANDLED;
738 else
739 OUTMSG (("Can only continue with recieved signal %d.\n", last_sig));
740 }
741
742 last_sig = TARGET_SIGNAL_0;
743
744 /* Get context for the currently selected thread. */
745 th = thread_rec (current_event.dwThreadId, FALSE);
746 if (th)
747 {
748 if (th->context.ContextFlags)
749 {
b80864fb
DJ
750 /* Move register values from the inferior into the thread
751 context structure. */
752 regcache_invalidate ();
753
754 if (step)
ed50f18f
PA
755 {
756 if (the_low_target.single_step != NULL)
757 (*the_low_target.single_step) (th);
758 else
759 error ("Single stepping is not supported "
760 "in this configuration.\n");
761 }
34b34921
PA
762
763 (*the_low_target.set_thread_context) (th, &current_event);
b80864fb
DJ
764 th->context.ContextFlags = 0;
765 }
766 }
767
768 /* Allow continuing with the same signal that interrupted us.
769 Otherwise complain. */
770
771 child_continue (continue_status, tid);
772}
773
255e7678
DJ
774static void
775win32_add_one_solib (const char *name, CORE_ADDR load_addr)
776{
777 char buf[MAX_PATH + 1];
778 char buf2[MAX_PATH + 1];
779
780#ifdef _WIN32_WCE
781 WIN32_FIND_DATA w32_fd;
782 WCHAR wname[MAX_PATH + 1];
783 mbstowcs (wname, name, MAX_PATH);
784 HANDLE h = FindFirstFile (wname, &w32_fd);
785#else
786 WIN32_FIND_DATAA w32_fd;
787 HANDLE h = FindFirstFileA (name, &w32_fd);
788#endif
789
790 if (h == INVALID_HANDLE_VALUE)
791 strcpy (buf, name);
792 else
793 {
794 FindClose (h);
795 strcpy (buf, name);
796#ifndef _WIN32_WCE
797 {
798 char cwd[MAX_PATH + 1];
799 char *p;
800 if (GetCurrentDirectoryA (MAX_PATH + 1, cwd))
801 {
802 p = strrchr (buf, '\\');
803 if (p)
804 p[1] = '\0';
805 SetCurrentDirectoryA (buf);
806 GetFullPathNameA (w32_fd.cFileName, MAX_PATH, buf, &p);
807 SetCurrentDirectoryA (cwd);
808 }
809 }
810#endif
811 }
812
813#ifdef __CYGWIN__
814 cygwin_conv_to_posix_path (buf, buf2);
815#else
816 strcpy (buf2, buf);
817#endif
818
819 loaded_dll (buf2, load_addr);
820}
821
822static char *
823get_image_name (HANDLE h, void *address, int unicode)
824{
825 static char buf[(2 * MAX_PATH) + 1];
826 DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
827 char *address_ptr;
828 int len = 0;
829 char b[2];
830 DWORD done;
831
832 /* Attempt to read the name of the dll that was detected.
833 This is documented to work only when actively debugging
834 a program. It will not work for attached processes. */
835 if (address == NULL)
836 return NULL;
837
838#ifdef _WIN32_WCE
839 /* Windows CE reports the address of the image name,
840 instead of an address of a pointer into the image name. */
841 address_ptr = address;
842#else
843 /* See if we could read the address of a string, and that the
844 address isn't null. */
845 if (!ReadProcessMemory (h, address, &address_ptr,
846 sizeof (address_ptr), &done)
847 || done != sizeof (address_ptr)
848 || !address_ptr)
849 return NULL;
850#endif
851
852 /* Find the length of the string */
853 while (ReadProcessMemory (h, address_ptr + len++ * size, &b, size, &done)
854 && (b[0] != 0 || b[size - 1] != 0) && done == size)
855 continue;
856
857 if (!unicode)
858 ReadProcessMemory (h, address_ptr, buf, len, &done);
859 else
860 {
861 WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR));
862 ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
863 &done);
864
865 WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, len, 0, 0);
866 }
867
868 return buf;
869}
870
871typedef BOOL (WINAPI *winapi_EnumProcessModules) (HANDLE, HMODULE *,
872 DWORD, LPDWORD);
873typedef BOOL (WINAPI *winapi_GetModuleInformation) (HANDLE, HMODULE,
874 LPMODULEINFO, DWORD);
875typedef DWORD (WINAPI *winapi_GetModuleFileNameExA) (HANDLE, HMODULE,
876 LPSTR, DWORD);
877
878static winapi_EnumProcessModules win32_EnumProcessModules;
879static winapi_GetModuleInformation win32_GetModuleInformation;
880static winapi_GetModuleFileNameExA win32_GetModuleFileNameExA;
881
882static BOOL
883load_psapi (void)
884{
885 static int psapi_loaded = 0;
886 static HMODULE dll = NULL;
887
888 if (!psapi_loaded)
889 {
890 psapi_loaded = 1;
891 dll = LoadLibrary (TEXT("psapi.dll"));
892 if (!dll)
893 return FALSE;
894 win32_EnumProcessModules =
895 GETPROCADDRESS (dll, EnumProcessModules);
896 win32_GetModuleInformation =
897 GETPROCADDRESS (dll, GetModuleInformation);
898 win32_GetModuleFileNameExA =
899 GETPROCADDRESS (dll, GetModuleFileNameExA);
900 }
901
902 return (win32_EnumProcessModules != NULL
903 && win32_GetModuleInformation != NULL
904 && win32_GetModuleFileNameExA != NULL);
905}
906
907static int
908psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
909{
910 DWORD len;
911 MODULEINFO mi;
912 size_t i;
913 HMODULE dh_buf[1];
914 HMODULE *DllHandle = dh_buf;
915 DWORD cbNeeded;
916 BOOL ok;
917
918 if (!load_psapi ())
919 goto failed;
920
921 cbNeeded = 0;
922 ok = (*win32_EnumProcessModules) (current_process_handle,
923 DllHandle,
924 sizeof (HMODULE),
925 &cbNeeded);
926
927 if (!ok || !cbNeeded)
928 goto failed;
929
930 DllHandle = (HMODULE *) alloca (cbNeeded);
931 if (!DllHandle)
932 goto failed;
933
934 ok = (*win32_EnumProcessModules) (current_process_handle,
935 DllHandle,
936 cbNeeded,
937 &cbNeeded);
938 if (!ok)
939 goto failed;
940
941 for (i = 0; i < ((size_t) cbNeeded / sizeof (HMODULE)); i++)
942 {
943 if (!(*win32_GetModuleInformation) (current_process_handle,
944 DllHandle[i],
945 &mi,
946 sizeof (mi)))
947 {
948 DWORD err = GetLastError ();
949 error ("Can't get module info: (error %d): %s\n",
950 (int) err, strwinerror (err));
951 }
952
953 if ((DWORD) (mi.lpBaseOfDll) == BaseAddress)
954 {
955 len = (*win32_GetModuleFileNameExA) (current_process_handle,
956 DllHandle[i],
957 dll_name_ret,
958 MAX_PATH);
959 if (len == 0)
960 {
961 DWORD err = GetLastError ();
962 error ("Error getting dll name: (error %d): %s\n",
963 (int) err, strwinerror (err));
964 }
965 return 1;
966 }
967 }
968
969failed:
970 dll_name_ret[0] = '\0';
971 return 0;
972}
973
974typedef HANDLE (WINAPI *winapi_CreateToolhelp32Snapshot) (DWORD, DWORD);
975typedef BOOL (WINAPI *winapi_Module32First) (HANDLE, LPMODULEENTRY32);
976typedef BOOL (WINAPI *winapi_Module32Next) (HANDLE, LPMODULEENTRY32);
977
978static winapi_CreateToolhelp32Snapshot win32_CreateToolhelp32Snapshot;
979static winapi_Module32First win32_Module32First;
980static winapi_Module32Next win32_Module32Next;
6b3d9b83
PA
981#ifdef _WIN32_WCE
982typedef BOOL (WINAPI *winapi_CloseToolhelp32Snapshot) (HANDLE);
983static winapi_CloseToolhelp32Snapshot win32_CloseToolhelp32Snapshot;
984#endif
255e7678
DJ
985
986static BOOL
987load_toolhelp (void)
988{
989 static int toolhelp_loaded = 0;
990 static HMODULE dll = NULL;
991
992 if (!toolhelp_loaded)
993 {
994 toolhelp_loaded = 1;
995#ifndef _WIN32_WCE
996 dll = GetModuleHandle (_T("KERNEL32.DLL"));
997#else
6b3d9b83 998 dll = LoadLibrary (L"TOOLHELP.DLL");
255e7678
DJ
999#endif
1000 if (!dll)
1001 return FALSE;
1002
1003 win32_CreateToolhelp32Snapshot =
1004 GETPROCADDRESS (dll, CreateToolhelp32Snapshot);
1005 win32_Module32First = GETPROCADDRESS (dll, Module32First);
1006 win32_Module32Next = GETPROCADDRESS (dll, Module32Next);
6b3d9b83
PA
1007#ifdef _WIN32_WCE
1008 win32_CloseToolhelp32Snapshot =
1009 GETPROCADDRESS (dll, CloseToolhelp32Snapshot);
1010#endif
255e7678
DJ
1011 }
1012
1013 return (win32_CreateToolhelp32Snapshot != NULL
1014 && win32_Module32First != NULL
6b3d9b83
PA
1015 && win32_Module32Next != NULL
1016#ifdef _WIN32_WCE
1017 && win32_CloseToolhelp32Snapshot != NULL
1018#endif
1019 );
255e7678
DJ
1020}
1021
1022static int
1023toolhelp_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
1024{
1025 HANDLE snapshot_module;
1026 MODULEENTRY32 modEntry = { sizeof (MODULEENTRY32) };
6b3d9b83 1027 int found = 0;
255e7678
DJ
1028
1029 if (!load_toolhelp ())
1030 return 0;
1031
1032 snapshot_module = win32_CreateToolhelp32Snapshot (TH32CS_SNAPMODULE,
1033 current_event.dwProcessId);
1034 if (snapshot_module == INVALID_HANDLE_VALUE)
1035 return 0;
1036
1037 /* Ignore the first module, which is the exe. */
6b3d9b83
PA
1038 if (win32_Module32First (snapshot_module, &modEntry))
1039 while (win32_Module32Next (snapshot_module, &modEntry))
1040 if ((DWORD) modEntry.modBaseAddr == BaseAddress)
1041 {
255e7678 1042#ifdef UNICODE
6b3d9b83 1043 wcstombs (dll_name_ret, modEntry.szExePath, MAX_PATH + 1);
255e7678 1044#else
6b3d9b83 1045 strcpy (dll_name_ret, modEntry.szExePath);
255e7678 1046#endif
6b3d9b83
PA
1047 found = 1;
1048 break;
1049 }
255e7678 1050
6b3d9b83
PA
1051#ifdef _WIN32_WCE
1052 win32_CloseToolhelp32Snapshot (snapshot_module);
1053#else
255e7678 1054 CloseHandle (snapshot_module);
6b3d9b83
PA
1055#endif
1056 return found;
255e7678
DJ
1057}
1058
1059static void
1060handle_load_dll (void)
1061{
1062 LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
1063 char dll_buf[MAX_PATH + 1];
1064 char *dll_name = NULL;
1065 DWORD load_addr;
1066
1067 dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
1068
1069 if (!psapi_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf)
1070 && !toolhelp_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf))
1071 dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
1072
1073 dll_name = dll_buf;
1074
1075 if (*dll_name == '\0')
1076 dll_name = get_image_name (current_process_handle,
1077 event->lpImageName, event->fUnicode);
1078 if (!dll_name)
1079 return;
1080
1081 /* The symbols in a dll are offset by 0x1000, which is the
1082 the offset from 0 of the first byte in an image - because
1083 of the file header and the section alignment. */
1084
1085 load_addr = (DWORD) event->lpBaseOfDll + 0x1000;
1086 win32_add_one_solib (dll_name, load_addr);
1087}
1088
1089static void
1090handle_unload_dll (void)
1091{
1092 CORE_ADDR load_addr =
1093 (CORE_ADDR) (DWORD) current_event.u.UnloadDll.lpBaseOfDll;
1094 load_addr += 0x1000;
1095 unloaded_dll (NULL, load_addr);
1096}
1097
34b34921 1098static void
b80864fb
DJ
1099handle_exception (struct target_waitstatus *ourstatus)
1100{
b80864fb
DJ
1101 DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode;
1102
1103 ourstatus->kind = TARGET_WAITKIND_STOPPED;
1104
b80864fb
DJ
1105 switch (code)
1106 {
1107 case EXCEPTION_ACCESS_VIOLATION:
1108 OUTMSG2 (("EXCEPTION_ACCESS_VIOLATION"));
1109 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
1110 break;
1111 case STATUS_STACK_OVERFLOW:
1112 OUTMSG2 (("STATUS_STACK_OVERFLOW"));
1113 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
1114 break;
1115 case STATUS_FLOAT_DENORMAL_OPERAND:
1116 OUTMSG2 (("STATUS_FLOAT_DENORMAL_OPERAND"));
1117 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1118 break;
1119 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1120 OUTMSG2 (("EXCEPTION_ARRAY_BOUNDS_EXCEEDED"));
1121 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1122 break;
1123 case STATUS_FLOAT_INEXACT_RESULT:
1124 OUTMSG2 (("STATUS_FLOAT_INEXACT_RESULT"));
1125 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1126 break;
1127 case STATUS_FLOAT_INVALID_OPERATION:
1128 OUTMSG2 (("STATUS_FLOAT_INVALID_OPERATION"));
1129 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1130 break;
1131 case STATUS_FLOAT_OVERFLOW:
1132 OUTMSG2 (("STATUS_FLOAT_OVERFLOW"));
1133 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1134 break;
1135 case STATUS_FLOAT_STACK_CHECK:
1136 OUTMSG2 (("STATUS_FLOAT_STACK_CHECK"));
1137 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1138 break;
1139 case STATUS_FLOAT_UNDERFLOW:
1140 OUTMSG2 (("STATUS_FLOAT_UNDERFLOW"));
1141 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1142 break;
1143 case STATUS_FLOAT_DIVIDE_BY_ZERO:
1144 OUTMSG2 (("STATUS_FLOAT_DIVIDE_BY_ZERO"));
1145 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1146 break;
1147 case STATUS_INTEGER_DIVIDE_BY_ZERO:
1148 OUTMSG2 (("STATUS_INTEGER_DIVIDE_BY_ZERO"));
1149 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1150 break;
1151 case STATUS_INTEGER_OVERFLOW:
1152 OUTMSG2 (("STATUS_INTEGER_OVERFLOW"));
1153 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1154 break;
1155 case EXCEPTION_BREAKPOINT:
1156 OUTMSG2 (("EXCEPTION_BREAKPOINT"));
1157 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
ed50f18f
PA
1158#ifdef _WIN32_WCE
1159 /* Remove the initial breakpoint. */
1160 check_breakpoints ((CORE_ADDR) (long) current_event
1161 .u.Exception.ExceptionRecord.ExceptionAddress);
1162#endif
b80864fb
DJ
1163 break;
1164 case DBG_CONTROL_C:
1165 OUTMSG2 (("DBG_CONTROL_C"));
1166 ourstatus->value.sig = TARGET_SIGNAL_INT;
1167 break;
1168 case DBG_CONTROL_BREAK:
1169 OUTMSG2 (("DBG_CONTROL_BREAK"));
1170 ourstatus->value.sig = TARGET_SIGNAL_INT;
1171 break;
1172 case EXCEPTION_SINGLE_STEP:
1173 OUTMSG2 (("EXCEPTION_SINGLE_STEP"));
1174 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
1175 break;
1176 case EXCEPTION_ILLEGAL_INSTRUCTION:
1177 OUTMSG2 (("EXCEPTION_ILLEGAL_INSTRUCTION"));
1178 ourstatus->value.sig = TARGET_SIGNAL_ILL;
1179 break;
1180 case EXCEPTION_PRIV_INSTRUCTION:
1181 OUTMSG2 (("EXCEPTION_PRIV_INSTRUCTION"));
1182 ourstatus->value.sig = TARGET_SIGNAL_ILL;
1183 break;
1184 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
1185 OUTMSG2 (("EXCEPTION_NONCONTINUABLE_EXCEPTION"));
1186 ourstatus->value.sig = TARGET_SIGNAL_ILL;
1187 break;
1188 default:
1189 if (current_event.u.Exception.dwFirstChance)
34b34921
PA
1190 {
1191 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
1192 return;
1193 }
b80864fb
DJ
1194 OUTMSG2 (("gdbserver: unknown target exception 0x%08lx at 0x%08lx",
1195 current_event.u.Exception.ExceptionRecord.ExceptionCode,
1196 (DWORD) current_event.u.Exception.ExceptionRecord.
1197 ExceptionAddress));
1198 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
1199 break;
1200 }
1201 OUTMSG2 (("\n"));
1202 last_sig = ourstatus->value.sig;
b80864fb
DJ
1203}
1204
34b34921
PA
1205/* Get the next event from the child. */
1206static void
b80864fb
DJ
1207get_child_debug_event (struct target_waitstatus *ourstatus)
1208{
1209 BOOL debug_event;
b80864fb
DJ
1210
1211 last_sig = TARGET_SIGNAL_0;
1212 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
1213
7390519e
PA
1214 /* Keep the wait time low enough for confortable remote interruption,
1215 but high enough so gdbserver doesn't become a bottleneck. */
1216 if (!(debug_event = WaitForDebugEvent (&current_event, 250)))
34b34921 1217 return;
b80864fb
DJ
1218
1219 current_inferior =
1220 (struct thread_info *) find_inferior_id (&all_threads,
1221 current_event.dwThreadId);
1222
34b34921 1223 switch (current_event.dwDebugEventCode)
b80864fb
DJ
1224 {
1225 case CREATE_THREAD_DEBUG_EVENT:
1226 OUTMSG2 (("gdbserver: kernel event CREATE_THREAD_DEBUG_EVENT "
1227 "for pid=%d tid=%x)\n",
1228 (unsigned) current_event.dwProcessId,
1229 (unsigned) current_event.dwThreadId));
1230
1231 /* Record the existence of this thread. */
34b34921 1232 child_add_thread (current_event.dwThreadId,
b80864fb 1233 current_event.u.CreateThread.hThread);
b80864fb
DJ
1234 break;
1235
1236 case EXIT_THREAD_DEBUG_EVENT:
1237 OUTMSG2 (("gdbserver: kernel event EXIT_THREAD_DEBUG_EVENT "
1238 "for pid=%d tid=%x\n",
1239 (unsigned) current_event.dwProcessId,
1240 (unsigned) current_event.dwThreadId));
1241 child_delete_thread (current_event.dwThreadId);
b80864fb
DJ
1242 break;
1243
1244 case CREATE_PROCESS_DEBUG_EVENT:
1245 OUTMSG2 (("gdbserver: kernel event CREATE_PROCESS_DEBUG_EVENT "
1246 "for pid=%d tid=%x\n",
1247 (unsigned) current_event.dwProcessId,
1248 (unsigned) current_event.dwThreadId));
1249 CloseHandle (current_event.u.CreateProcessInfo.hFile);
1250
1251 current_process_handle = current_event.u.CreateProcessInfo.hProcess;
1252 main_thread_id = current_event.dwThreadId;
1253
1254 ourstatus->kind = TARGET_WAITKIND_EXECD;
1255 ourstatus->value.execd_pathname = "Main executable";
1256
1257 /* Add the main thread. */
34b34921
PA
1258 child_add_thread (main_thread_id,
1259 current_event.u.CreateProcessInfo.hThread);
b80864fb 1260
34b34921 1261 ourstatus->value.related_pid = current_event.dwThreadId;
ed50f18f
PA
1262#ifdef _WIN32_WCE
1263 /* Windows CE doesn't set the initial breakpoint automatically
1264 like the desktop versions of Windows do. We add it explicitly
1265 here. It will be removed as soon as it is hit. */
1266 set_breakpoint_at ((CORE_ADDR) (long) current_event.u
1267 .CreateProcessInfo.lpStartAddress,
1268 delete_breakpoint_at);
1269#endif
b80864fb
DJ
1270 break;
1271
1272 case EXIT_PROCESS_DEBUG_EVENT:
1273 OUTMSG2 (("gdbserver: kernel event EXIT_PROCESS_DEBUG_EVENT "
1274 "for pid=%d tid=%x\n",
1275 (unsigned) current_event.dwProcessId,
1276 (unsigned) current_event.dwThreadId));
1277 ourstatus->kind = TARGET_WAITKIND_EXITED;
1278 ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
1279 CloseHandle (current_process_handle);
9d606399 1280 current_process_handle = NULL;
b80864fb
DJ
1281 break;
1282
1283 case LOAD_DLL_DEBUG_EVENT:
1284 OUTMSG2 (("gdbserver: kernel event LOAD_DLL_DEBUG_EVENT "
1285 "for pid=%d tid=%x\n",
1286 (unsigned) current_event.dwProcessId,
1287 (unsigned) current_event.dwThreadId));
1288 CloseHandle (current_event.u.LoadDll.hFile);
255e7678 1289 handle_load_dll ();
b80864fb
DJ
1290
1291 ourstatus->kind = TARGET_WAITKIND_LOADED;
255e7678 1292 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
b80864fb
DJ
1293 break;
1294
1295 case UNLOAD_DLL_DEBUG_EVENT:
1296 OUTMSG2 (("gdbserver: kernel event UNLOAD_DLL_DEBUG_EVENT "
1297 "for pid=%d tid=%x\n",
1298 (unsigned) current_event.dwProcessId,
1299 (unsigned) current_event.dwThreadId));
255e7678
DJ
1300 handle_unload_dll ();
1301 ourstatus->kind = TARGET_WAITKIND_LOADED;
1302 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
b80864fb
DJ
1303 break;
1304
1305 case EXCEPTION_DEBUG_EVENT:
1306 OUTMSG2 (("gdbserver: kernel event EXCEPTION_DEBUG_EVENT "
1307 "for pid=%d tid=%x\n",
1308 (unsigned) current_event.dwProcessId,
1309 (unsigned) current_event.dwThreadId));
34b34921 1310 handle_exception (ourstatus);
b80864fb
DJ
1311 break;
1312
1313 case OUTPUT_DEBUG_STRING_EVENT:
1314 /* A message from the kernel (or Cygwin). */
1315 OUTMSG2 (("gdbserver: kernel event OUTPUT_DEBUG_STRING_EVENT "
1316 "for pid=%d tid=%x\n",
1317 (unsigned) current_event.dwProcessId,
1318 (unsigned) current_event.dwThreadId));
bce7165d 1319 handle_output_debug_string (ourstatus);
b80864fb
DJ
1320 break;
1321
1322 default:
1323 OUTMSG2 (("gdbserver: kernel event unknown "
1324 "for pid=%d tid=%x code=%ld\n",
1325 (unsigned) current_event.dwProcessId,
1326 (unsigned) current_event.dwThreadId,
1327 current_event.dwDebugEventCode));
1328 break;
1329 }
1330
1331 current_inferior =
1332 (struct thread_info *) find_inferior_id (&all_threads,
1333 current_event.dwThreadId);
b80864fb
DJ
1334}
1335
1336/* Wait for the inferior process to change state.
1337 STATUS will be filled in with a response code to send to GDB.
1338 Returns the signal which caused the process to stop. */
1339static unsigned char
1340win32_wait (char *status)
1341{
1342 struct target_waitstatus our_status;
1343
1344 *status = 'T';
1345
1346 while (1)
1347 {
7390519e
PA
1348 /* Check if GDB sent us an interrupt request. */
1349 check_remote_input_interrupt_request ();
1350
b80864fb
DJ
1351 get_child_debug_event (&our_status);
1352
34b34921 1353 switch (our_status.kind)
b80864fb 1354 {
34b34921 1355 case TARGET_WAITKIND_EXITED:
b80864fb
DJ
1356 OUTMSG2 (("Child exited with retcode = %x\n",
1357 our_status.value.integer));
1358
1359 *status = 'W';
1360
1361 child_fetch_inferior_registers (-1);
1362
1363 return our_status.value.integer;
34b34921 1364 case TARGET_WAITKIND_STOPPED:
255e7678 1365 case TARGET_WAITKIND_LOADED:
f72f3e60 1366 OUTMSG2 (("Child Stopped with signal = %d \n",
ed50f18f 1367 our_status.value.sig));
b80864fb
DJ
1368
1369 *status = 'T';
1370
1371 child_fetch_inferior_registers (-1);
1372
255e7678
DJ
1373 if (our_status.kind == TARGET_WAITKIND_LOADED
1374 && !server_waiting)
1375 {
1376 /* When gdb connects, we want to be stopped at the
1377 initial breakpoint, not in some dll load event. */
1378 child_continue (DBG_CONTINUE, -1);
1379 break;
1380 }
1381
b80864fb 1382 return our_status.value.sig;
34b34921
PA
1383 default:
1384 OUTMSG (("Ignoring unknown internal event, %d\n", our_status.kind));
1385 /* fall-through */
1386 case TARGET_WAITKIND_SPURIOUS:
34b34921
PA
1387 case TARGET_WAITKIND_EXECD:
1388 /* do nothing, just continue */
1389 child_continue (DBG_CONTINUE, -1);
1390 break;
b80864fb 1391 }
b80864fb
DJ
1392 }
1393}
1394
1395/* Fetch registers from the inferior process.
1396 If REGNO is -1, fetch all registers; otherwise, fetch at least REGNO. */
1397static void
1398win32_fetch_inferior_registers (int regno)
1399{
1400 child_fetch_inferior_registers (regno);
1401}
1402
1403/* Store registers to the inferior process.
1404 If REGNO is -1, store all registers; otherwise, store at least REGNO. */
1405static void
1406win32_store_inferior_registers (int regno)
1407{
1408 child_store_inferior_registers (regno);
1409}
1410
1411/* Read memory from the inferior process. This should generally be
1412 called through read_inferior_memory, which handles breakpoint shadowing.
1413 Read LEN bytes at MEMADDR into a buffer at MYADDR. */
1414static int
1415win32_read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
1416{
ed50f18f 1417 return child_xfer_memory (memaddr, (char *) myaddr, len, 0, 0) != len;
b80864fb
DJ
1418}
1419
1420/* Write memory to the inferior process. This should generally be
1421 called through write_inferior_memory, which handles breakpoint shadowing.
1422 Write LEN bytes from the buffer at MYADDR to MEMADDR.
1423 Returns 0 on success and errno on failure. */
1424static int
1425win32_write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr,
1426 int len)
1427{
1428 return child_xfer_memory (memaddr, (char *) myaddr, len, 1, 0) != len;
1429}
1430
7390519e
PA
1431/* Send an interrupt request to the inferior process. */
1432static void
1433win32_request_interrupt (void)
1434{
1435 winapi_DebugBreakProcess DebugBreakProcess;
1436 winapi_GenerateConsoleCtrlEvent GenerateConsoleCtrlEvent;
1437
1438#ifdef _WIN32_WCE
1439 HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
1440#else
1441 HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
1442#endif
1443
1444 GenerateConsoleCtrlEvent = GETPROCADDRESS (dll, GenerateConsoleCtrlEvent);
1445
1446 if (GenerateConsoleCtrlEvent != NULL
1447 && GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, current_process_id))
1448 return;
1449
1450 /* GenerateConsoleCtrlEvent can fail if process id being debugged is
1451 not a process group id.
1452 Fallback to XP/Vista 'DebugBreakProcess', which generates a
1453 breakpoint exception in the interior process. */
1454
1455 DebugBreakProcess = GETPROCADDRESS (dll, DebugBreakProcess);
1456
1457 if (DebugBreakProcess != NULL
1458 && DebugBreakProcess (current_process_handle))
1459 return;
1460
1461 OUTMSG (("Could not interrupt process.\n"));
1462}
1463
820f2bda
PA
1464static const char *
1465win32_arch_string (void)
1466{
ed50f18f 1467 return the_low_target.arch_string;
820f2bda
PA
1468}
1469
b80864fb
DJ
1470static struct target_ops win32_target_ops = {
1471 win32_create_inferior,
1472 win32_attach,
1473 win32_kill,
1474 win32_detach,
444d6139 1475 win32_join,
b80864fb
DJ
1476 win32_thread_alive,
1477 win32_resume,
1478 win32_wait,
1479 win32_fetch_inferior_registers,
1480 win32_store_inferior_registers,
1481 win32_read_inferior_memory,
1482 win32_write_inferior_memory,
820f2bda 1483 NULL,
7390519e 1484 win32_request_interrupt,
820f2bda
PA
1485 NULL,
1486 NULL,
1487 NULL,
1488 NULL,
1489 NULL,
1490 NULL,
1491 NULL,
1492 win32_arch_string
b80864fb
DJ
1493};
1494
1495/* Initialize the Win32 backend. */
1496void
1497initialize_low (void)
1498{
1499 set_target_ops (&win32_target_ops);
ed50f18f
PA
1500 if (the_low_target.breakpoint != NULL)
1501 set_breakpoint_data (the_low_target.breakpoint,
1502 the_low_target.breakpoint_len);
b80864fb
DJ
1503 init_registers ();
1504}