* gdb.base/unload.c (dlopen, dlsym): Use the TEXT macro to convert
[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);
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
34d86ddd
PA
1069 /* Windows does not report the image name of the dlls in the debug
1070 event on attaches. We resort to iterating over the list of
1071 loaded dlls looking for a match by image base. */
1072 if (!psapi_get_dll_name ((DWORD) event->lpBaseOfDll, dll_buf))
1073 {
1074 if (!server_waiting)
1075 /* On some versions of Windows and Windows CE, we can't create
1076 toolhelp snapshots while the inferior is stopped in a
1077 LOAD_DLL_DEBUG_EVENT due to a dll load, but we can while
1078 Windows is reporting the already loaded dlls. */
1079 toolhelp_get_dll_name ((DWORD) event->lpBaseOfDll, dll_buf);
1080 }
255e7678
DJ
1081
1082 dll_name = dll_buf;
1083
1084 if (*dll_name == '\0')
1085 dll_name = get_image_name (current_process_handle,
1086 event->lpImageName, event->fUnicode);
1087 if (!dll_name)
1088 return;
1089
1090 /* The symbols in a dll are offset by 0x1000, which is the
1091 the offset from 0 of the first byte in an image - because
1092 of the file header and the section alignment. */
1093
1094 load_addr = (DWORD) event->lpBaseOfDll + 0x1000;
1095 win32_add_one_solib (dll_name, load_addr);
1096}
1097
1098static void
1099handle_unload_dll (void)
1100{
1101 CORE_ADDR load_addr =
1102 (CORE_ADDR) (DWORD) current_event.u.UnloadDll.lpBaseOfDll;
1103 load_addr += 0x1000;
1104 unloaded_dll (NULL, load_addr);
1105}
1106
34b34921 1107static void
b80864fb
DJ
1108handle_exception (struct target_waitstatus *ourstatus)
1109{
b80864fb
DJ
1110 DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode;
1111
1112 ourstatus->kind = TARGET_WAITKIND_STOPPED;
1113
b80864fb
DJ
1114 switch (code)
1115 {
1116 case EXCEPTION_ACCESS_VIOLATION:
1117 OUTMSG2 (("EXCEPTION_ACCESS_VIOLATION"));
1118 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
1119 break;
1120 case STATUS_STACK_OVERFLOW:
1121 OUTMSG2 (("STATUS_STACK_OVERFLOW"));
1122 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
1123 break;
1124 case STATUS_FLOAT_DENORMAL_OPERAND:
1125 OUTMSG2 (("STATUS_FLOAT_DENORMAL_OPERAND"));
1126 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1127 break;
1128 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1129 OUTMSG2 (("EXCEPTION_ARRAY_BOUNDS_EXCEEDED"));
1130 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1131 break;
1132 case STATUS_FLOAT_INEXACT_RESULT:
1133 OUTMSG2 (("STATUS_FLOAT_INEXACT_RESULT"));
1134 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1135 break;
1136 case STATUS_FLOAT_INVALID_OPERATION:
1137 OUTMSG2 (("STATUS_FLOAT_INVALID_OPERATION"));
1138 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1139 break;
1140 case STATUS_FLOAT_OVERFLOW:
1141 OUTMSG2 (("STATUS_FLOAT_OVERFLOW"));
1142 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1143 break;
1144 case STATUS_FLOAT_STACK_CHECK:
1145 OUTMSG2 (("STATUS_FLOAT_STACK_CHECK"));
1146 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1147 break;
1148 case STATUS_FLOAT_UNDERFLOW:
1149 OUTMSG2 (("STATUS_FLOAT_UNDERFLOW"));
1150 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1151 break;
1152 case STATUS_FLOAT_DIVIDE_BY_ZERO:
1153 OUTMSG2 (("STATUS_FLOAT_DIVIDE_BY_ZERO"));
1154 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1155 break;
1156 case STATUS_INTEGER_DIVIDE_BY_ZERO:
1157 OUTMSG2 (("STATUS_INTEGER_DIVIDE_BY_ZERO"));
1158 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1159 break;
1160 case STATUS_INTEGER_OVERFLOW:
1161 OUTMSG2 (("STATUS_INTEGER_OVERFLOW"));
1162 ourstatus->value.sig = TARGET_SIGNAL_FPE;
1163 break;
1164 case EXCEPTION_BREAKPOINT:
1165 OUTMSG2 (("EXCEPTION_BREAKPOINT"));
1166 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
ed50f18f
PA
1167#ifdef _WIN32_WCE
1168 /* Remove the initial breakpoint. */
1169 check_breakpoints ((CORE_ADDR) (long) current_event
1170 .u.Exception.ExceptionRecord.ExceptionAddress);
1171#endif
b80864fb
DJ
1172 break;
1173 case DBG_CONTROL_C:
1174 OUTMSG2 (("DBG_CONTROL_C"));
1175 ourstatus->value.sig = TARGET_SIGNAL_INT;
1176 break;
1177 case DBG_CONTROL_BREAK:
1178 OUTMSG2 (("DBG_CONTROL_BREAK"));
1179 ourstatus->value.sig = TARGET_SIGNAL_INT;
1180 break;
1181 case EXCEPTION_SINGLE_STEP:
1182 OUTMSG2 (("EXCEPTION_SINGLE_STEP"));
1183 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
1184 break;
1185 case EXCEPTION_ILLEGAL_INSTRUCTION:
1186 OUTMSG2 (("EXCEPTION_ILLEGAL_INSTRUCTION"));
1187 ourstatus->value.sig = TARGET_SIGNAL_ILL;
1188 break;
1189 case EXCEPTION_PRIV_INSTRUCTION:
1190 OUTMSG2 (("EXCEPTION_PRIV_INSTRUCTION"));
1191 ourstatus->value.sig = TARGET_SIGNAL_ILL;
1192 break;
1193 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
1194 OUTMSG2 (("EXCEPTION_NONCONTINUABLE_EXCEPTION"));
1195 ourstatus->value.sig = TARGET_SIGNAL_ILL;
1196 break;
1197 default:
1198 if (current_event.u.Exception.dwFirstChance)
34b34921
PA
1199 {
1200 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
1201 return;
1202 }
b80864fb
DJ
1203 OUTMSG2 (("gdbserver: unknown target exception 0x%08lx at 0x%08lx",
1204 current_event.u.Exception.ExceptionRecord.ExceptionCode,
1205 (DWORD) current_event.u.Exception.ExceptionRecord.
1206 ExceptionAddress));
1207 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
1208 break;
1209 }
1210 OUTMSG2 (("\n"));
1211 last_sig = ourstatus->value.sig;
b80864fb
DJ
1212}
1213
34b34921
PA
1214/* Get the next event from the child. */
1215static void
b80864fb
DJ
1216get_child_debug_event (struct target_waitstatus *ourstatus)
1217{
1218 BOOL debug_event;
b80864fb
DJ
1219
1220 last_sig = TARGET_SIGNAL_0;
1221 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
1222
7390519e
PA
1223 /* Keep the wait time low enough for confortable remote interruption,
1224 but high enough so gdbserver doesn't become a bottleneck. */
1225 if (!(debug_event = WaitForDebugEvent (&current_event, 250)))
34b34921 1226 return;
b80864fb
DJ
1227
1228 current_inferior =
1229 (struct thread_info *) find_inferior_id (&all_threads,
1230 current_event.dwThreadId);
1231
34b34921 1232 switch (current_event.dwDebugEventCode)
b80864fb
DJ
1233 {
1234 case CREATE_THREAD_DEBUG_EVENT:
1235 OUTMSG2 (("gdbserver: kernel event CREATE_THREAD_DEBUG_EVENT "
1236 "for pid=%d tid=%x)\n",
1237 (unsigned) current_event.dwProcessId,
1238 (unsigned) current_event.dwThreadId));
1239
1240 /* Record the existence of this thread. */
34b34921 1241 child_add_thread (current_event.dwThreadId,
b80864fb 1242 current_event.u.CreateThread.hThread);
b80864fb
DJ
1243 break;
1244
1245 case EXIT_THREAD_DEBUG_EVENT:
1246 OUTMSG2 (("gdbserver: kernel event EXIT_THREAD_DEBUG_EVENT "
1247 "for pid=%d tid=%x\n",
1248 (unsigned) current_event.dwProcessId,
1249 (unsigned) current_event.dwThreadId));
1250 child_delete_thread (current_event.dwThreadId);
b80864fb
DJ
1251 break;
1252
1253 case CREATE_PROCESS_DEBUG_EVENT:
1254 OUTMSG2 (("gdbserver: kernel event CREATE_PROCESS_DEBUG_EVENT "
1255 "for pid=%d tid=%x\n",
1256 (unsigned) current_event.dwProcessId,
1257 (unsigned) current_event.dwThreadId));
1258 CloseHandle (current_event.u.CreateProcessInfo.hFile);
1259
1260 current_process_handle = current_event.u.CreateProcessInfo.hProcess;
1261 main_thread_id = current_event.dwThreadId;
1262
1263 ourstatus->kind = TARGET_WAITKIND_EXECD;
1264 ourstatus->value.execd_pathname = "Main executable";
1265
1266 /* Add the main thread. */
34b34921
PA
1267 child_add_thread (main_thread_id,
1268 current_event.u.CreateProcessInfo.hThread);
b80864fb 1269
34b34921 1270 ourstatus->value.related_pid = current_event.dwThreadId;
ed50f18f
PA
1271#ifdef _WIN32_WCE
1272 /* Windows CE doesn't set the initial breakpoint automatically
1273 like the desktop versions of Windows do. We add it explicitly
1274 here. It will be removed as soon as it is hit. */
1275 set_breakpoint_at ((CORE_ADDR) (long) current_event.u
1276 .CreateProcessInfo.lpStartAddress,
1277 delete_breakpoint_at);
1278#endif
b80864fb
DJ
1279 break;
1280
1281 case EXIT_PROCESS_DEBUG_EVENT:
1282 OUTMSG2 (("gdbserver: kernel event EXIT_PROCESS_DEBUG_EVENT "
1283 "for pid=%d tid=%x\n",
1284 (unsigned) current_event.dwProcessId,
1285 (unsigned) current_event.dwThreadId));
1286 ourstatus->kind = TARGET_WAITKIND_EXITED;
1287 ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
1288 CloseHandle (current_process_handle);
9d606399 1289 current_process_handle = NULL;
b80864fb
DJ
1290 break;
1291
1292 case LOAD_DLL_DEBUG_EVENT:
1293 OUTMSG2 (("gdbserver: kernel event LOAD_DLL_DEBUG_EVENT "
1294 "for pid=%d tid=%x\n",
1295 (unsigned) current_event.dwProcessId,
1296 (unsigned) current_event.dwThreadId));
1297 CloseHandle (current_event.u.LoadDll.hFile);
255e7678 1298 handle_load_dll ();
b80864fb
DJ
1299
1300 ourstatus->kind = TARGET_WAITKIND_LOADED;
255e7678 1301 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
b80864fb
DJ
1302 break;
1303
1304 case UNLOAD_DLL_DEBUG_EVENT:
1305 OUTMSG2 (("gdbserver: kernel event UNLOAD_DLL_DEBUG_EVENT "
1306 "for pid=%d tid=%x\n",
1307 (unsigned) current_event.dwProcessId,
1308 (unsigned) current_event.dwThreadId));
255e7678
DJ
1309 handle_unload_dll ();
1310 ourstatus->kind = TARGET_WAITKIND_LOADED;
1311 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
b80864fb
DJ
1312 break;
1313
1314 case EXCEPTION_DEBUG_EVENT:
1315 OUTMSG2 (("gdbserver: kernel event EXCEPTION_DEBUG_EVENT "
1316 "for pid=%d tid=%x\n",
1317 (unsigned) current_event.dwProcessId,
1318 (unsigned) current_event.dwThreadId));
34b34921 1319 handle_exception (ourstatus);
b80864fb
DJ
1320 break;
1321
1322 case OUTPUT_DEBUG_STRING_EVENT:
1323 /* A message from the kernel (or Cygwin). */
1324 OUTMSG2 (("gdbserver: kernel event OUTPUT_DEBUG_STRING_EVENT "
1325 "for pid=%d tid=%x\n",
1326 (unsigned) current_event.dwProcessId,
1327 (unsigned) current_event.dwThreadId));
bce7165d 1328 handle_output_debug_string (ourstatus);
b80864fb
DJ
1329 break;
1330
1331 default:
1332 OUTMSG2 (("gdbserver: kernel event unknown "
1333 "for pid=%d tid=%x code=%ld\n",
1334 (unsigned) current_event.dwProcessId,
1335 (unsigned) current_event.dwThreadId,
1336 current_event.dwDebugEventCode));
1337 break;
1338 }
1339
1340 current_inferior =
1341 (struct thread_info *) find_inferior_id (&all_threads,
1342 current_event.dwThreadId);
b80864fb
DJ
1343}
1344
1345/* Wait for the inferior process to change state.
1346 STATUS will be filled in with a response code to send to GDB.
1347 Returns the signal which caused the process to stop. */
1348static unsigned char
1349win32_wait (char *status)
1350{
1351 struct target_waitstatus our_status;
1352
1353 *status = 'T';
1354
1355 while (1)
1356 {
7390519e
PA
1357 /* Check if GDB sent us an interrupt request. */
1358 check_remote_input_interrupt_request ();
1359
b80864fb
DJ
1360 get_child_debug_event (&our_status);
1361
34b34921 1362 switch (our_status.kind)
b80864fb 1363 {
34b34921 1364 case TARGET_WAITKIND_EXITED:
b80864fb
DJ
1365 OUTMSG2 (("Child exited with retcode = %x\n",
1366 our_status.value.integer));
1367
1368 *status = 'W';
1369
1370 child_fetch_inferior_registers (-1);
1371
1372 return our_status.value.integer;
34b34921 1373 case TARGET_WAITKIND_STOPPED:
255e7678 1374 case TARGET_WAITKIND_LOADED:
f72f3e60 1375 OUTMSG2 (("Child Stopped with signal = %d \n",
ed50f18f 1376 our_status.value.sig));
b80864fb
DJ
1377
1378 *status = 'T';
1379
1380 child_fetch_inferior_registers (-1);
1381
255e7678
DJ
1382 if (our_status.kind == TARGET_WAITKIND_LOADED
1383 && !server_waiting)
1384 {
1385 /* When gdb connects, we want to be stopped at the
1386 initial breakpoint, not in some dll load event. */
1387 child_continue (DBG_CONTINUE, -1);
1388 break;
1389 }
1390
b80864fb 1391 return our_status.value.sig;
34b34921
PA
1392 default:
1393 OUTMSG (("Ignoring unknown internal event, %d\n", our_status.kind));
1394 /* fall-through */
1395 case TARGET_WAITKIND_SPURIOUS:
34b34921
PA
1396 case TARGET_WAITKIND_EXECD:
1397 /* do nothing, just continue */
1398 child_continue (DBG_CONTINUE, -1);
1399 break;
b80864fb 1400 }
b80864fb
DJ
1401 }
1402}
1403
1404/* Fetch registers from the inferior process.
1405 If REGNO is -1, fetch all registers; otherwise, fetch at least REGNO. */
1406static void
1407win32_fetch_inferior_registers (int regno)
1408{
1409 child_fetch_inferior_registers (regno);
1410}
1411
1412/* Store registers to the inferior process.
1413 If REGNO is -1, store all registers; otherwise, store at least REGNO. */
1414static void
1415win32_store_inferior_registers (int regno)
1416{
1417 child_store_inferior_registers (regno);
1418}
1419
1420/* Read memory from the inferior process. This should generally be
1421 called through read_inferior_memory, which handles breakpoint shadowing.
1422 Read LEN bytes at MEMADDR into a buffer at MYADDR. */
1423static int
1424win32_read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
1425{
ed50f18f 1426 return child_xfer_memory (memaddr, (char *) myaddr, len, 0, 0) != len;
b80864fb
DJ
1427}
1428
1429/* Write memory to the inferior process. This should generally be
1430 called through write_inferior_memory, which handles breakpoint shadowing.
1431 Write LEN bytes from the buffer at MYADDR to MEMADDR.
1432 Returns 0 on success and errno on failure. */
1433static int
1434win32_write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr,
1435 int len)
1436{
1437 return child_xfer_memory (memaddr, (char *) myaddr, len, 1, 0) != len;
1438}
1439
7390519e
PA
1440/* Send an interrupt request to the inferior process. */
1441static void
1442win32_request_interrupt (void)
1443{
1444 winapi_DebugBreakProcess DebugBreakProcess;
1445 winapi_GenerateConsoleCtrlEvent GenerateConsoleCtrlEvent;
1446
1447#ifdef _WIN32_WCE
1448 HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
1449#else
1450 HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
1451#endif
1452
1453 GenerateConsoleCtrlEvent = GETPROCADDRESS (dll, GenerateConsoleCtrlEvent);
1454
1455 if (GenerateConsoleCtrlEvent != NULL
1456 && GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, current_process_id))
1457 return;
1458
1459 /* GenerateConsoleCtrlEvent can fail if process id being debugged is
1460 not a process group id.
1461 Fallback to XP/Vista 'DebugBreakProcess', which generates a
1462 breakpoint exception in the interior process. */
1463
1464 DebugBreakProcess = GETPROCADDRESS (dll, DebugBreakProcess);
1465
1466 if (DebugBreakProcess != NULL
1467 && DebugBreakProcess (current_process_handle))
1468 return;
1469
1470 OUTMSG (("Could not interrupt process.\n"));
1471}
1472
820f2bda
PA
1473static const char *
1474win32_arch_string (void)
1475{
ed50f18f 1476 return the_low_target.arch_string;
820f2bda
PA
1477}
1478
b80864fb
DJ
1479static struct target_ops win32_target_ops = {
1480 win32_create_inferior,
1481 win32_attach,
1482 win32_kill,
1483 win32_detach,
444d6139 1484 win32_join,
b80864fb
DJ
1485 win32_thread_alive,
1486 win32_resume,
1487 win32_wait,
1488 win32_fetch_inferior_registers,
1489 win32_store_inferior_registers,
1490 win32_read_inferior_memory,
1491 win32_write_inferior_memory,
820f2bda 1492 NULL,
7390519e 1493 win32_request_interrupt,
820f2bda
PA
1494 NULL,
1495 NULL,
1496 NULL,
1497 NULL,
1498 NULL,
1499 NULL,
1500 NULL,
1501 win32_arch_string
b80864fb
DJ
1502};
1503
1504/* Initialize the Win32 backend. */
1505void
1506initialize_low (void)
1507{
1508 set_target_ops (&win32_target_ops);
ed50f18f
PA
1509 if (the_low_target.breakpoint != NULL)
1510 set_breakpoint_data (the_low_target.breakpoint,
1511 the_low_target.breakpoint_len);
b80864fb
DJ
1512 init_registers ();
1513}
This page took 0.172208 seconds and 4 git commands to generate.