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