* win32-low.c: Commit leftover changes from 2007-03-29.
[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
10 the Free Software Foundation; either version 2 of the License, or
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
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
22
23#include "server.h"
24#include "regcache.h"
25#include "gdb/signals.h"
ed50f18f
PA
26#include "mem-break.h"
27#include "win32-low.h"
b80864fb
DJ
28
29#include <windows.h>
ed50f18f 30#include <winnt.h>
b80864fb
DJ
31#include <imagehlp.h>
32#include <psapi.h>
33#include <sys/param.h>
34#include <malloc.h>
35#include <process.h>
36
37#ifndef USE_WIN32API
38#include <sys/cygwin.h>
39#endif
40
41#define LOG 0
42
43#define OUTMSG(X) do { printf X; fflush (stdout); } while (0)
44#if LOG
45#define OUTMSG2(X) do { printf X; fflush (stdout); } while (0)
46#else
ed50f18f
PA
47#define OUTMSG2(X) do ; while (0)
48#endif
49
50#ifndef _T
51#define _T(x) TEXT (x)
52#endif
53
54#ifndef COUNTOF
55#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0]))
b80864fb
DJ
56#endif
57
b80864fb
DJ
58int using_threads = 1;
59
60/* Globals. */
61static HANDLE current_process_handle = NULL;
62static DWORD current_process_id = 0;
63static enum target_signal last_sig = TARGET_SIGNAL_0;
64
65/* The current debug event from WaitForDebugEvent. */
66static DEBUG_EVENT current_event;
67
68static int debug_registers_changed = 0;
69static int debug_registers_used = 0;
ed50f18f
PA
70
71#define NUM_REGS (the_low_target.num_regs)
b80864fb
DJ
72
73typedef BOOL winapi_DebugActiveProcessStop (DWORD dwProcessId);
74typedef BOOL winapi_DebugSetProcessKillOnExit (BOOL KillOnExit);
75
ed50f18f
PA
76#ifndef CONTEXT_EXTENDED_REGISTERS
77#define CONTEXT_EXTENDED_REGISTERS 0
78#endif
79
80#ifndef CONTEXT_FLOATING_POINT
81#define CONTEXT_FLOATING_POINT 0
82#endif
83
84#ifndef CONTEXT_DEBUG_REGISTERS
85#define CONTEXT_DEBUG_REGISTERS 0
86#endif
87
b80864fb
DJ
88#define CONTEXT_DEBUGGER (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
89#define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS \
90 | CONTEXT_EXTENDED_REGISTERS
91
b80864fb
DJ
92static DWORD main_thread_id = 0;
93
94/* Get the thread ID from the current selected inferior (the current
95 thread). */
96static DWORD
97current_inferior_tid (void)
98{
41093d81 99 win32_thread_info *th = inferior_target_data (current_inferior);
b80864fb
DJ
100 return th->tid;
101}
102
103/* Find a thread record given a thread id. If GET_CONTEXT is set then
104 also retrieve the context for this thread. */
41093d81 105static win32_thread_info *
b80864fb
DJ
106thread_rec (DWORD id, int get_context)
107{
108 struct thread_info *thread;
41093d81 109 win32_thread_info *th;
b80864fb
DJ
110
111 thread = (struct thread_info *) find_inferior_id (&all_threads, id);
112 if (thread == NULL)
113 return NULL;
114
115 th = inferior_target_data (thread);
116 if (!th->suspend_count && get_context)
117 {
118 if (get_context > 0 && id != current_event.dwThreadId)
119 th->suspend_count = SuspendThread (th->h) + 1;
120 else if (get_context < 0)
121 th->suspend_count = -1;
122
123 th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
124
125 GetThreadContext (th->h, &th->context);
126
127 if (id == current_event.dwThreadId)
128 {
129 /* Copy dr values from that thread. */
ed50f18f
PA
130 if (the_low_target.store_debug_registers != NULL)
131 (*the_low_target.store_debug_registers) (th);
b80864fb
DJ
132 }
133 }
134
135 return th;
136}
137
138/* Add a thread to the thread list. */
41093d81 139static win32_thread_info *
b80864fb
DJ
140child_add_thread (DWORD tid, HANDLE h)
141{
41093d81 142 win32_thread_info *th;
b80864fb
DJ
143
144 if ((th = thread_rec (tid, FALSE)))
145 return th;
146
41093d81 147 th = (win32_thread_info *) malloc (sizeof (*th));
b80864fb
DJ
148 memset (th, 0, sizeof (*th));
149 th->tid = tid;
150 th->h = h;
151
152 add_thread (tid, th, (unsigned int) tid);
153 set_inferior_regcache_data ((struct thread_info *)
154 find_inferior_id (&all_threads, tid),
155 new_register_cache ());
156
157 /* Set the debug registers for the new thread if they are used. */
ed50f18f
PA
158 if (debug_registers_used
159 && the_low_target.load_debug_registers != NULL)
b80864fb
DJ
160 {
161 /* Only change the value of the debug registers. */
162 th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
163
164 GetThreadContext (th->h, &th->context);
165
ed50f18f
PA
166 (*the_low_target.load_debug_registers) (th);
167
b80864fb
DJ
168 SetThreadContext (th->h, &th->context);
169 th->context.ContextFlags = 0;
170 }
171
172 return th;
173}
174
175/* Delete a thread from the list of threads. */
176static void
177delete_thread_info (struct inferior_list_entry *thread)
178{
41093d81 179 win32_thread_info *th = inferior_target_data ((struct thread_info *) thread);
b80864fb
DJ
180
181 remove_thread ((struct thread_info *) thread);
182 CloseHandle (th->h);
183 free (th);
184}
185
186/* Delete a thread from the list of threads. */
187static void
188child_delete_thread (DWORD id)
189{
190 struct inferior_list_entry *thread;
191
192 /* If the last thread is exiting, just return. */
193 if (all_threads.head == all_threads.tail)
194 return;
195
196 thread = find_inferior_id (&all_threads, id);
197 if (thread == NULL)
198 return;
199
200 delete_thread_info (thread);
201}
202
203/* Transfer memory from/to the debugged process. */
204static int
205child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
206 int write, struct target_ops *target)
207{
208 SIZE_T done;
209 long addr = (long) memaddr;
210
211 if (write)
212 {
213 WriteProcessMemory (current_process_handle, (LPVOID) addr,
214 (LPCVOID) our, len, &done);
215 FlushInstructionCache (current_process_handle, (LPCVOID) addr, len);
216 }
217 else
218 {
219 ReadProcessMemory (current_process_handle, (LPCVOID) addr, (LPVOID) our,
220 len, &done);
221 }
222 return done;
223}
224
225/* Generally, what has the program done? */
226enum target_waitkind
227{
228 /* The program has exited. The exit status is in value.integer. */
229 TARGET_WAITKIND_EXITED,
230
231 /* The program has stopped with a signal. Which signal is in
232 value.sig. */
233 TARGET_WAITKIND_STOPPED,
234
235 /* The program is letting us know that it dynamically loaded something
236 (e.g. it called load(2) on AIX). */
237 TARGET_WAITKIND_LOADED,
238
239 /* The program has exec'ed a new executable file. The new file's
240 pathname is pointed to by value.execd_pathname. */
241
242 TARGET_WAITKIND_EXECD,
243
244 /* Nothing happened, but we stopped anyway. This perhaps should be handled
245 within target_wait, but I'm not sure target_wait should be resuming the
246 inferior. */
247 TARGET_WAITKIND_SPURIOUS,
248};
249
250struct target_waitstatus
251{
252 enum target_waitkind kind;
253
254 /* Forked child pid, execd pathname, exit status or signal number. */
255 union
256 {
257 int integer;
258 enum target_signal sig;
259 int related_pid;
260 char *execd_pathname;
261 int syscall_id;
262 }
263 value;
264};
265
ed50f18f
PA
266/* Return a pointer into a CONTEXT field indexed by gdb register number.
267 Return a pointer to an dummy register holding zero if there is no
268 corresponding CONTEXT field for the given register number. */
269char *
270regptr (CONTEXT* c, int r)
271{
272 if (the_low_target.regmap[r] < 0)
273 {
274 static ULONG zero;
275 /* Always force value to zero, in case the user tried to write
276 to this register before. */
277 zero = 0;
278 return (char *) &zero;
279 }
280 else
281 return (char *) c + the_low_target.regmap[r];
282}
b80864fb 283
b80864fb 284
ed50f18f 285/* Clear out any old thread list and reinitialize it to a pristine
b80864fb
DJ
286 state. */
287static void
288child_init_thread_list (void)
289{
290 for_each_inferior (&all_threads, delete_thread_info);
291}
292
293static void
294do_initial_child_stuff (DWORD pid)
295{
b80864fb
DJ
296 last_sig = TARGET_SIGNAL_0;
297
298 debug_registers_changed = 0;
299 debug_registers_used = 0;
ed50f18f 300
b80864fb
DJ
301 memset (&current_event, 0, sizeof (current_event));
302
303 child_init_thread_list ();
ed50f18f
PA
304
305 if (the_low_target.initial_stuff != NULL)
306 (*the_low_target.initial_stuff) ();
b80864fb
DJ
307}
308
309/* Resume all artificially suspended threads if we are continuing
310 execution. */
311static int
312continue_one_thread (struct inferior_list_entry *this_thread, void *id_ptr)
313{
314 struct thread_info *thread = (struct thread_info *) this_thread;
315 int thread_id = * (int *) id_ptr;
41093d81 316 win32_thread_info *th = inferior_target_data (thread);
b80864fb
DJ
317 int i;
318
319 if ((thread_id == -1 || thread_id == th->tid)
320 && th->suspend_count)
321 {
322 for (i = 0; i < th->suspend_count; i++)
323 (void) ResumeThread (th->h);
324 th->suspend_count = 0;
325 if (debug_registers_changed)
326 {
327 /* Only change the value of the debug registers. */
328 th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
ed50f18f
PA
329
330 if (the_low_target.load_debug_registers != NULL)
331 the_low_target.load_debug_registers (th);
332
b80864fb
DJ
333 SetThreadContext (th->h, &th->context);
334 th->context.ContextFlags = 0;
335 }
336 }
337
338 return 0;
339}
340
341static BOOL
342child_continue (DWORD continue_status, int thread_id)
343{
344 BOOL res;
345
346 res = ContinueDebugEvent (current_event.dwProcessId,
347 current_event.dwThreadId, continue_status);
348 continue_status = 0;
349 if (res)
350 find_inferior (&all_threads, continue_one_thread, &thread_id);
351
352 debug_registers_changed = 0;
353 return res;
354}
355
b80864fb
DJ
356/* Fetch register(s) from the current thread context. */
357static void
358child_fetch_inferior_registers (int r)
359{
360 int regno;
41093d81 361 win32_thread_info *th = thread_rec (current_inferior_tid (), TRUE);
b80864fb
DJ
362 if (r == -1 || r == 0 || r > NUM_REGS)
363 child_fetch_inferior_registers (NUM_REGS);
364 else
365 for (regno = 0; regno < r; regno++)
ed50f18f 366 (*the_low_target.fetch_inferior_registers) (th, regno);
b80864fb
DJ
367}
368
369/* Get register from gdbserver regcache data. */
370static void
41093d81 371do_child_store_inferior_registers (win32_thread_info *th, int r)
b80864fb 372{
ed50f18f 373 collect_register (r, regptr (&th->context, r));
b80864fb
DJ
374}
375
376/* Store a new register value into the current thread context. We don't
377 change the program's context until later, when we resume it. */
378static void
379child_store_inferior_registers (int r)
380{
381 int regno;
41093d81 382 win32_thread_info *th = thread_rec (current_inferior_tid (), TRUE);
b80864fb
DJ
383 if (r == -1 || r == 0 || r > NUM_REGS)
384 child_store_inferior_registers (NUM_REGS);
385 else
386 for (regno = 0; regno < r; regno++)
387 do_child_store_inferior_registers (th, regno);
388}
389
ed50f18f
PA
390/* Map the Windows error number in ERROR to a locale-dependent error
391 message string and return a pointer to it. Typically, the values
392 for ERROR come from GetLastError.
393
394 The string pointed to shall not be modified by the application,
395 but may be overwritten by a subsequent call to strwinerror
396
397 The strwinerror function does not change the current setting
398 of GetLastError. */
399
400char *
401strwinerror (DWORD error)
402{
403 static char buf[1024];
404 TCHAR *msgbuf;
405 DWORD lasterr = GetLastError ();
406 DWORD chars = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
407 | FORMAT_MESSAGE_ALLOCATE_BUFFER,
408 NULL,
409 error,
410 0, /* Default language */
411 (LPVOID)&msgbuf,
412 0,
413 NULL);
414 if (chars != 0)
415 {
416 /* If there is an \r\n appended, zap it. */
417 if (chars >= 2
418 && msgbuf[chars - 2] == '\r'
419 && msgbuf[chars - 1] == '\n')
420 {
421 chars -= 2;
422 msgbuf[chars] = 0;
423 }
424
425 if (chars > ((COUNTOF (buf)) - 1))
426 {
427 chars = COUNTOF (buf) - 1;
428 msgbuf [chars] = 0;
429 }
430
431#ifdef UNICODE
432 wcstombs (buf, msgbuf, chars + 1);
433#else
434 strncpy (buf, msgbuf, chars + 1);
435#endif
436 LocalFree (msgbuf);
437 }
438 else
439 sprintf (buf, "unknown win32 error (%ld)", error);
440
441 SetLastError (lasterr);
442 return buf;
443}
444
b80864fb
DJ
445/* Start a new process.
446 PROGRAM is a path to the program to execute.
447 ARGS is a standard NULL-terminated array of arguments,
448 to be passed to the inferior as ``argv''.
449 Returns the new PID on success, -1 on failure. Registers the new
450 process with the process list. */
451static int
452win32_create_inferior (char *program, char **program_args)
453{
454#ifndef USE_WIN32API
455 char real_path[MAXPATHLEN];
456 char *orig_path, *new_path, *path_ptr;
457#endif
b80864fb
DJ
458 BOOL ret;
459 DWORD flags;
460 char *args;
461 int argslen;
462 int argc;
ed50f18f
PA
463 PROCESS_INFORMATION pi;
464#ifndef __MINGW32CE__
465 STARTUPINFO si = { sizeof (STARTUPINFO) };
466 char *winenv = NULL;
467#else
468 wchar_t *wargs, *wprogram;
469#endif
b80864fb
DJ
470
471 if (!program)
472 error ("No executable specified, specify executable to debug.\n");
473
b80864fb
DJ
474 flags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
475
476#ifndef USE_WIN32API
477 orig_path = NULL;
478 path_ptr = getenv ("PATH");
479 if (path_ptr)
480 {
481 orig_path = alloca (strlen (path_ptr) + 1);
482 new_path = alloca (cygwin_posix_to_win32_path_list_buf_size (path_ptr));
483 strcpy (orig_path, path_ptr);
484 cygwin_posix_to_win32_path_list (path_ptr, new_path);
485 setenv ("PATH", new_path, 1);
486 }
487 cygwin_conv_to_win32_path (program, real_path);
488 program = real_path;
489#endif
490
ed50f18f 491 argslen = 1;
b80864fb
DJ
492 for (argc = 1; program_args[argc]; argc++)
493 argslen += strlen (program_args[argc]) + 1;
494 args = alloca (argslen);
ed50f18f 495 args[0] = '\0';
b80864fb
DJ
496 for (argc = 1; program_args[argc]; argc++)
497 {
498 /* FIXME: Can we do better about quoting? How does Cygwin
499 handle this? */
500 strcat (args, " ");
501 strcat (args, program_args[argc]);
502 }
ed50f18f 503 OUTMSG2 (("Command line is \"%s\"\n", args));
b80864fb 504
ed50f18f 505#ifdef CREATE_NEW_PROCESS_GROUP
b80864fb 506 flags |= CREATE_NEW_PROCESS_GROUP;
ed50f18f 507#endif
b80864fb 508
ed50f18f
PA
509#ifdef __MINGW32CE__
510 to_back_slashes (program);
511 wargs = alloca (argslen * sizeof (wchar_t));
512 mbstowcs (wargs, args, argslen);
513 wprogram = alloca ((strlen (program) + 1) * sizeof (wchar_t));
514 mbstowcs (wprogram, program, strlen (program) + 1);
515 ret = CreateProcessW (wprogram, /* image name */
516 wargs, /* command line */
517 NULL, /* security, not supported */
518 NULL, /* thread, not supported */
519 FALSE, /* inherit handles, not supported */
520 flags, /* start flags */
521 NULL, /* environment, not supported */
522 NULL, /* current directory, not supported */
523 NULL, /* start info, not supported */
524 &pi); /* proc info */
525#else
526 ret = CreateProcess (program, /* image name */
527 args, /* command line */
528 NULL, /* security */
b80864fb
DJ
529 NULL, /* thread */
530 TRUE, /* inherit handles */
531 flags, /* start flags */
ed50f18f
PA
532 winenv, /* environment */
533 NULL, /* current directory */
534 &si, /* start info */
535 &pi); /* proc info */
536#endif
b80864fb
DJ
537
538#ifndef USE_WIN32API
539 if (orig_path)
540 setenv ("PATH", orig_path, 1);
541#endif
542
543 if (!ret)
544 {
ed50f18f
PA
545 DWORD err = GetLastError ();
546 error ("Error creating process \"%s%s\", (error %d): %s\n",
547 program, args, (int) err, strwinerror (err));
b80864fb
DJ
548 }
549 else
550 {
551 OUTMSG2 (("Process created: %s\n", (char *) args));
552 }
553
ed50f18f
PA
554#ifndef _WIN32_WCE
555 /* On Windows CE this handle can't be closed. The OS reuses
556 it in the debug events, while the 9x/NT versions of Windows
557 probably use a DuplicateHandle'd one. */
b80864fb 558 CloseHandle (pi.hThread);
ed50f18f 559#endif
b80864fb
DJ
560
561 current_process_handle = pi.hProcess;
562 current_process_id = pi.dwProcessId;
563
564 do_initial_child_stuff (current_process_id);
565
566 return current_process_id;
567}
568
569/* Attach to a running process.
570 PID is the process ID to attach to, specified by the user
571 or a higher layer. */
572static int
573win32_attach (unsigned long pid)
574{
575 int res = 0;
b80864fb 576 winapi_DebugActiveProcessStop *DebugActiveProcessStop = NULL;
b80864fb 577
ed50f18f
PA
578 winapi_DebugSetProcessKillOnExit *DebugSetProcessKillOnExit = NULL;
579#ifdef _WIN32_WCE
580 HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
581#else
582 HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
583#endif
584 DebugActiveProcessStop = (winapi_DebugActiveProcessStop *)
585 GetProcAddress (dll, _T("DebugActiveProcessStop"));
586 DebugSetProcessKillOnExit = (winapi_DebugSetProcessKillOnExit *)
587 GetProcAddress (dll, _T("DebugSetProcessKillOnExit"));
b80864fb
DJ
588
589 res = DebugActiveProcess (pid) ? 1 : 0;
590
591 if (!res)
592 error ("Attach to process failed.");
593
594 if (DebugSetProcessKillOnExit != NULL)
595 DebugSetProcessKillOnExit (FALSE);
596
597 current_process_id = pid;
598 current_process_handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
599
600 if (current_process_handle == NULL)
601 {
602 res = 0;
603 if (DebugActiveProcessStop != NULL)
604 DebugActiveProcessStop (current_process_id);
605 }
606
607 if (res)
608 do_initial_child_stuff (pid);
609
b80864fb
DJ
610 return res;
611}
612
bce7165d
PA
613/* Handle OUTPUT_DEBUG_STRING_EVENT from child process. */
614static void
615handle_output_debug_string (struct target_waitstatus *ourstatus)
616{
617#define READ_BUFFER_LEN 1024
618 CORE_ADDR addr;
619 char s[READ_BUFFER_LEN + 1] = { 0 };
620 DWORD nbytes = current_event.u.DebugString.nDebugStringLength;
621
622 if (nbytes == 0)
623 return;
624
625 if (nbytes > READ_BUFFER_LEN)
626 nbytes = READ_BUFFER_LEN;
627
628 addr = (CORE_ADDR) (size_t) current_event.u.DebugString.lpDebugStringData;
629
630 if (current_event.u.DebugString.fUnicode)
631 {
632 /* The event tells us how many bytes, not chars, even
633 in Unicode. */
634 WCHAR buffer[(READ_BUFFER_LEN + 1) / sizeof (WCHAR)] = { 0 };
635 if (read_inferior_memory (addr, (unsigned char *) buffer, nbytes) != 0)
636 return;
637 wcstombs (s, buffer, (nbytes + 1) / sizeof (WCHAR));
638 }
639 else
640 {
641 if (read_inferior_memory (addr, (unsigned char *) s, nbytes) != 0)
642 return;
643 }
644
645 if (strncmp (s, "cYg", 3) != 0)
646 monitor_output (s);
647#undef READ_BUFFER_LEN
648}
649
b80864fb
DJ
650/* Kill all inferiors. */
651static void
652win32_kill (void)
653{
ed50f18f
PA
654 win32_thread_info *current_thread;
655
9d606399
DJ
656 if (current_process_handle == NULL)
657 return;
658
b80864fb
DJ
659 TerminateProcess (current_process_handle, 0);
660 for (;;)
661 {
662 if (!child_continue (DBG_CONTINUE, -1))
663 break;
664 if (!WaitForDebugEvent (&current_event, INFINITE))
665 break;
666 if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
667 break;
bce7165d
PA
668 else if (current_event.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT)
669 {
670 struct target_waitstatus our_status = { 0 };
671 handle_output_debug_string (&our_status);
672 }
b80864fb 673 }
ed50f18f
PA
674
675 CloseHandle (current_process_handle);
676
677 current_thread = inferior_target_data (current_inferior);
678 if (current_thread && current_thread->h)
679 {
680 /* This may fail in an attached process, so don't check. */
681 (void) CloseHandle (current_thread->h);
682 }
b80864fb
DJ
683}
684
685/* Detach from all inferiors. */
686static void
687win32_detach (void)
688{
b80864fb
DJ
689 winapi_DebugActiveProcessStop *DebugActiveProcessStop = NULL;
690 winapi_DebugSetProcessKillOnExit *DebugSetProcessKillOnExit = NULL;
ed50f18f
PA
691#ifdef _WIN32_WCE
692 HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
693#else
694 HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
695#endif
696 DebugActiveProcessStop = (winapi_DebugActiveProcessStop *)
697 GetProcAddress (dll, _T("DebugActiveProcessStop"));
698 DebugSetProcessKillOnExit = (winapi_DebugSetProcessKillOnExit *)
699 GetProcAddress (dll, _T("DebugSetProcessKillOnExit"));
b80864fb
DJ
700
701 if (DebugSetProcessKillOnExit != NULL)
702 DebugSetProcessKillOnExit (FALSE);
703
704 if (DebugActiveProcessStop != NULL)
705 DebugActiveProcessStop (current_process_id);
706 else
707 win32_kill ();
b80864fb
DJ
708}
709
710/* Return 1 iff the thread with thread ID TID is alive. */
711static int
712win32_thread_alive (unsigned long tid)
713{
714 int res;
715
716 /* Our thread list is reliable; don't bother to poll target
717 threads. */
718 if (find_inferior_id (&all_threads, tid) != NULL)
719 res = 1;
720 else
721 res = 0;
722 return res;
723}
724
725/* Resume the inferior process. RESUME_INFO describes how we want
726 to resume. */
727static void
728win32_resume (struct thread_resume *resume_info)
729{
730 DWORD tid;
731 enum target_signal sig;
732 int step;
41093d81 733 win32_thread_info *th;
b80864fb
DJ
734 DWORD continue_status = DBG_CONTINUE;
735
736 /* This handles the very limited set of resume packets that GDB can
737 currently produce. */
738
739 if (resume_info[0].thread == -1)
740 tid = -1;
741 else if (resume_info[1].thread == -1 && !resume_info[1].leave_stopped)
742 tid = -1;
743 else
744 /* Yes, we're ignoring resume_info[0].thread. It'd be tricky to make
745 the Windows resume code do the right thing for thread switching. */
746 tid = current_event.dwThreadId;
747
748 if (resume_info[0].thread != -1)
749 {
750 sig = resume_info[0].sig;
751 step = resume_info[0].step;
752 }
753 else
754 {
755 sig = 0;
756 step = 0;
757 }
758
759 if (sig != TARGET_SIGNAL_0)
760 {
761 if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
762 {
763 OUTMSG (("Cannot continue with signal %d here.\n", sig));
764 }
765 else if (sig == last_sig)
766 continue_status = DBG_EXCEPTION_NOT_HANDLED;
767 else
768 OUTMSG (("Can only continue with recieved signal %d.\n", last_sig));
769 }
770
771 last_sig = TARGET_SIGNAL_0;
772
773 /* Get context for the currently selected thread. */
774 th = thread_rec (current_event.dwThreadId, FALSE);
775 if (th)
776 {
777 if (th->context.ContextFlags)
778 {
779 if (debug_registers_changed)
ed50f18f
PA
780 if (the_low_target.load_debug_registers != NULL)
781 (*the_low_target.load_debug_registers) (th);
b80864fb
DJ
782
783 /* Move register values from the inferior into the thread
784 context structure. */
785 regcache_invalidate ();
786
787 if (step)
ed50f18f
PA
788 {
789 if (the_low_target.single_step != NULL)
790 (*the_low_target.single_step) (th);
791 else
792 error ("Single stepping is not supported "
793 "in this configuration.\n");
794 }
b80864fb
DJ
795 SetThreadContext (th->h, &th->context);
796 th->context.ContextFlags = 0;
797 }
798 }
799
800 /* Allow continuing with the same signal that interrupted us.
801 Otherwise complain. */
802
803 child_continue (continue_status, tid);
804}
805
806static int
807handle_exception (struct target_waitstatus *ourstatus)
808{
41093d81 809 win32_thread_info *th;
b80864fb
DJ
810 DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode;
811
812 ourstatus->kind = TARGET_WAITKIND_STOPPED;
813
814 /* Record the context of the current thread. */
815 th = thread_rec (current_event.dwThreadId, -1);
816
817 switch (code)
818 {
819 case EXCEPTION_ACCESS_VIOLATION:
820 OUTMSG2 (("EXCEPTION_ACCESS_VIOLATION"));
821 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
822 break;
823 case STATUS_STACK_OVERFLOW:
824 OUTMSG2 (("STATUS_STACK_OVERFLOW"));
825 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
826 break;
827 case STATUS_FLOAT_DENORMAL_OPERAND:
828 OUTMSG2 (("STATUS_FLOAT_DENORMAL_OPERAND"));
829 ourstatus->value.sig = TARGET_SIGNAL_FPE;
830 break;
831 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
832 OUTMSG2 (("EXCEPTION_ARRAY_BOUNDS_EXCEEDED"));
833 ourstatus->value.sig = TARGET_SIGNAL_FPE;
834 break;
835 case STATUS_FLOAT_INEXACT_RESULT:
836 OUTMSG2 (("STATUS_FLOAT_INEXACT_RESULT"));
837 ourstatus->value.sig = TARGET_SIGNAL_FPE;
838 break;
839 case STATUS_FLOAT_INVALID_OPERATION:
840 OUTMSG2 (("STATUS_FLOAT_INVALID_OPERATION"));
841 ourstatus->value.sig = TARGET_SIGNAL_FPE;
842 break;
843 case STATUS_FLOAT_OVERFLOW:
844 OUTMSG2 (("STATUS_FLOAT_OVERFLOW"));
845 ourstatus->value.sig = TARGET_SIGNAL_FPE;
846 break;
847 case STATUS_FLOAT_STACK_CHECK:
848 OUTMSG2 (("STATUS_FLOAT_STACK_CHECK"));
849 ourstatus->value.sig = TARGET_SIGNAL_FPE;
850 break;
851 case STATUS_FLOAT_UNDERFLOW:
852 OUTMSG2 (("STATUS_FLOAT_UNDERFLOW"));
853 ourstatus->value.sig = TARGET_SIGNAL_FPE;
854 break;
855 case STATUS_FLOAT_DIVIDE_BY_ZERO:
856 OUTMSG2 (("STATUS_FLOAT_DIVIDE_BY_ZERO"));
857 ourstatus->value.sig = TARGET_SIGNAL_FPE;
858 break;
859 case STATUS_INTEGER_DIVIDE_BY_ZERO:
860 OUTMSG2 (("STATUS_INTEGER_DIVIDE_BY_ZERO"));
861 ourstatus->value.sig = TARGET_SIGNAL_FPE;
862 break;
863 case STATUS_INTEGER_OVERFLOW:
864 OUTMSG2 (("STATUS_INTEGER_OVERFLOW"));
865 ourstatus->value.sig = TARGET_SIGNAL_FPE;
866 break;
867 case EXCEPTION_BREAKPOINT:
868 OUTMSG2 (("EXCEPTION_BREAKPOINT"));
869 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
ed50f18f
PA
870#ifdef _WIN32_WCE
871 /* Remove the initial breakpoint. */
872 check_breakpoints ((CORE_ADDR) (long) current_event
873 .u.Exception.ExceptionRecord.ExceptionAddress);
874#endif
b80864fb
DJ
875 break;
876 case DBG_CONTROL_C:
877 OUTMSG2 (("DBG_CONTROL_C"));
878 ourstatus->value.sig = TARGET_SIGNAL_INT;
879 break;
880 case DBG_CONTROL_BREAK:
881 OUTMSG2 (("DBG_CONTROL_BREAK"));
882 ourstatus->value.sig = TARGET_SIGNAL_INT;
883 break;
884 case EXCEPTION_SINGLE_STEP:
885 OUTMSG2 (("EXCEPTION_SINGLE_STEP"));
886 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
887 break;
888 case EXCEPTION_ILLEGAL_INSTRUCTION:
889 OUTMSG2 (("EXCEPTION_ILLEGAL_INSTRUCTION"));
890 ourstatus->value.sig = TARGET_SIGNAL_ILL;
891 break;
892 case EXCEPTION_PRIV_INSTRUCTION:
893 OUTMSG2 (("EXCEPTION_PRIV_INSTRUCTION"));
894 ourstatus->value.sig = TARGET_SIGNAL_ILL;
895 break;
896 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
897 OUTMSG2 (("EXCEPTION_NONCONTINUABLE_EXCEPTION"));
898 ourstatus->value.sig = TARGET_SIGNAL_ILL;
899 break;
900 default:
901 if (current_event.u.Exception.dwFirstChance)
902 return 0;
903 OUTMSG2 (("gdbserver: unknown target exception 0x%08lx at 0x%08lx",
904 current_event.u.Exception.ExceptionRecord.ExceptionCode,
905 (DWORD) current_event.u.Exception.ExceptionRecord.
906 ExceptionAddress));
907 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
908 break;
909 }
910 OUTMSG2 (("\n"));
911 last_sig = ourstatus->value.sig;
912 return 1;
913}
914
915/* Get the next event from the child. Return 1 if the event requires
916 handling. */
917static int
918get_child_debug_event (struct target_waitstatus *ourstatus)
919{
920 BOOL debug_event;
921 DWORD continue_status, event_code;
41093d81
PA
922 win32_thread_info *th = NULL;
923 static win32_thread_info dummy_thread_info;
b80864fb
DJ
924 int retval = 0;
925
926in:
927
928 last_sig = TARGET_SIGNAL_0;
929 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
930
931 if (!(debug_event = WaitForDebugEvent (&current_event, 1000)))
932 goto out;
933
934 current_inferior =
935 (struct thread_info *) find_inferior_id (&all_threads,
936 current_event.dwThreadId);
937
938 continue_status = DBG_CONTINUE;
939 event_code = current_event.dwDebugEventCode;
940
941 switch (event_code)
942 {
943 case CREATE_THREAD_DEBUG_EVENT:
944 OUTMSG2 (("gdbserver: kernel event CREATE_THREAD_DEBUG_EVENT "
945 "for pid=%d tid=%x)\n",
946 (unsigned) current_event.dwProcessId,
947 (unsigned) current_event.dwThreadId));
948
949 /* Record the existence of this thread. */
950 th = child_add_thread (current_event.dwThreadId,
951 current_event.u.CreateThread.hThread);
952
953 retval = current_event.dwThreadId;
954 break;
955
956 case EXIT_THREAD_DEBUG_EVENT:
957 OUTMSG2 (("gdbserver: kernel event EXIT_THREAD_DEBUG_EVENT "
958 "for pid=%d tid=%x\n",
959 (unsigned) current_event.dwProcessId,
960 (unsigned) current_event.dwThreadId));
961 child_delete_thread (current_event.dwThreadId);
962 th = &dummy_thread_info;
963 break;
964
965 case CREATE_PROCESS_DEBUG_EVENT:
966 OUTMSG2 (("gdbserver: kernel event CREATE_PROCESS_DEBUG_EVENT "
967 "for pid=%d tid=%x\n",
968 (unsigned) current_event.dwProcessId,
969 (unsigned) current_event.dwThreadId));
970 CloseHandle (current_event.u.CreateProcessInfo.hFile);
971
972 current_process_handle = current_event.u.CreateProcessInfo.hProcess;
973 main_thread_id = current_event.dwThreadId;
974
975 ourstatus->kind = TARGET_WAITKIND_EXECD;
976 ourstatus->value.execd_pathname = "Main executable";
977
978 /* Add the main thread. */
979 th =
980 child_add_thread (main_thread_id,
981 current_event.u.CreateProcessInfo.hThread);
982
983 retval = ourstatus->value.related_pid = current_event.dwThreadId;
ed50f18f
PA
984#ifdef _WIN32_WCE
985 /* Windows CE doesn't set the initial breakpoint automatically
986 like the desktop versions of Windows do. We add it explicitly
987 here. It will be removed as soon as it is hit. */
988 set_breakpoint_at ((CORE_ADDR) (long) current_event.u
989 .CreateProcessInfo.lpStartAddress,
990 delete_breakpoint_at);
991#endif
b80864fb
DJ
992 break;
993
994 case EXIT_PROCESS_DEBUG_EVENT:
995 OUTMSG2 (("gdbserver: kernel event EXIT_PROCESS_DEBUG_EVENT "
996 "for pid=%d tid=%x\n",
997 (unsigned) current_event.dwProcessId,
998 (unsigned) current_event.dwThreadId));
999 ourstatus->kind = TARGET_WAITKIND_EXITED;
1000 ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
1001 CloseHandle (current_process_handle);
9d606399 1002 current_process_handle = NULL;
b80864fb
DJ
1003 retval = main_thread_id;
1004 break;
1005
1006 case LOAD_DLL_DEBUG_EVENT:
1007 OUTMSG2 (("gdbserver: kernel event LOAD_DLL_DEBUG_EVENT "
1008 "for pid=%d tid=%x\n",
1009 (unsigned) current_event.dwProcessId,
1010 (unsigned) current_event.dwThreadId));
1011 CloseHandle (current_event.u.LoadDll.hFile);
1012
1013 ourstatus->kind = TARGET_WAITKIND_LOADED;
1014 ourstatus->value.integer = 0;
1015 retval = main_thread_id;
1016 break;
1017
1018 case UNLOAD_DLL_DEBUG_EVENT:
1019 OUTMSG2 (("gdbserver: kernel event UNLOAD_DLL_DEBUG_EVENT "
1020 "for pid=%d tid=%x\n",
1021 (unsigned) current_event.dwProcessId,
1022 (unsigned) current_event.dwThreadId));
1023 break;
1024
1025 case EXCEPTION_DEBUG_EVENT:
1026 OUTMSG2 (("gdbserver: kernel event EXCEPTION_DEBUG_EVENT "
1027 "for pid=%d tid=%x\n",
1028 (unsigned) current_event.dwProcessId,
1029 (unsigned) current_event.dwThreadId));
1030 retval = handle_exception (ourstatus);
1031 break;
1032
1033 case OUTPUT_DEBUG_STRING_EVENT:
1034 /* A message from the kernel (or Cygwin). */
1035 OUTMSG2 (("gdbserver: kernel event OUTPUT_DEBUG_STRING_EVENT "
1036 "for pid=%d tid=%x\n",
1037 (unsigned) current_event.dwProcessId,
1038 (unsigned) current_event.dwThreadId));
bce7165d 1039 handle_output_debug_string (ourstatus);
b80864fb
DJ
1040 break;
1041
1042 default:
1043 OUTMSG2 (("gdbserver: kernel event unknown "
1044 "for pid=%d tid=%x code=%ld\n",
1045 (unsigned) current_event.dwProcessId,
1046 (unsigned) current_event.dwThreadId,
1047 current_event.dwDebugEventCode));
1048 break;
1049 }
1050
1051 current_inferior =
1052 (struct thread_info *) find_inferior_id (&all_threads,
1053 current_event.dwThreadId);
1054
1055 if (!retval || (event_code != EXCEPTION_DEBUG_EVENT && event_code != EXIT_PROCESS_DEBUG_EVENT))
1056 {
1057 child_continue (continue_status, -1);
1058 goto in;
1059 }
1060
1061 if (th == NULL)
1062 thread_rec (current_event.dwThreadId, TRUE);
1063
1064out:
1065 return retval;
1066}
1067
1068/* Wait for the inferior process to change state.
1069 STATUS will be filled in with a response code to send to GDB.
1070 Returns the signal which caused the process to stop. */
1071static unsigned char
1072win32_wait (char *status)
1073{
1074 struct target_waitstatus our_status;
1075
1076 *status = 'T';
1077
1078 while (1)
1079 {
1080 get_child_debug_event (&our_status);
1081
1082 if (our_status.kind == TARGET_WAITKIND_EXITED)
1083 {
1084 OUTMSG2 (("Child exited with retcode = %x\n",
1085 our_status.value.integer));
1086
1087 *status = 'W';
1088
1089 child_fetch_inferior_registers (-1);
1090
1091 return our_status.value.integer;
1092 }
1093 else if (our_status.kind == TARGET_WAITKIND_STOPPED)
1094 {
ed50f18f 1095#ifndef __MINGW32CE__
b80864fb
DJ
1096 OUTMSG2 (("Child Stopped with signal = %x \n",
1097 WSTOPSIG (our_status.value.sig)));
ed50f18f
PA
1098#else
1099 OUTMSG2 (("Child Stopped with signal = %x \n",
1100 our_status.value.sig));
1101#endif
b80864fb
DJ
1102
1103 *status = 'T';
1104
1105 child_fetch_inferior_registers (-1);
1106
1107 return our_status.value.sig;
1108 }
1109 else
1110 OUTMSG (("Ignoring unknown internal event, %d\n", our_status.kind));
1111
1112 {
1113 struct thread_resume resume;
1114 resume.thread = -1;
1115 resume.step = 0;
1116 resume.sig = 0;
1117 resume.leave_stopped = 0;
1118 win32_resume (&resume);
1119 }
1120 }
1121}
1122
1123/* Fetch registers from the inferior process.
1124 If REGNO is -1, fetch all registers; otherwise, fetch at least REGNO. */
1125static void
1126win32_fetch_inferior_registers (int regno)
1127{
1128 child_fetch_inferior_registers (regno);
1129}
1130
1131/* Store registers to the inferior process.
1132 If REGNO is -1, store all registers; otherwise, store at least REGNO. */
1133static void
1134win32_store_inferior_registers (int regno)
1135{
1136 child_store_inferior_registers (regno);
1137}
1138
1139/* Read memory from the inferior process. This should generally be
1140 called through read_inferior_memory, which handles breakpoint shadowing.
1141 Read LEN bytes at MEMADDR into a buffer at MYADDR. */
1142static int
1143win32_read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
1144{
ed50f18f 1145 return child_xfer_memory (memaddr, (char *) myaddr, len, 0, 0) != len;
b80864fb
DJ
1146}
1147
1148/* Write memory to the inferior process. This should generally be
1149 called through write_inferior_memory, which handles breakpoint shadowing.
1150 Write LEN bytes from the buffer at MYADDR to MEMADDR.
1151 Returns 0 on success and errno on failure. */
1152static int
1153win32_write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr,
1154 int len)
1155{
1156 return child_xfer_memory (memaddr, (char *) myaddr, len, 1, 0) != len;
1157}
1158
820f2bda
PA
1159static const char *
1160win32_arch_string (void)
1161{
ed50f18f 1162 return the_low_target.arch_string;
820f2bda
PA
1163}
1164
b80864fb
DJ
1165static struct target_ops win32_target_ops = {
1166 win32_create_inferior,
1167 win32_attach,
1168 win32_kill,
1169 win32_detach,
1170 win32_thread_alive,
1171 win32_resume,
1172 win32_wait,
1173 win32_fetch_inferior_registers,
1174 win32_store_inferior_registers,
1175 win32_read_inferior_memory,
1176 win32_write_inferior_memory,
820f2bda
PA
1177 NULL,
1178 NULL,
1179 NULL,
1180 NULL,
1181 NULL,
1182 NULL,
1183 NULL,
1184 NULL,
1185 NULL,
1186 win32_arch_string
b80864fb
DJ
1187};
1188
1189/* Initialize the Win32 backend. */
1190void
1191initialize_low (void)
1192{
1193 set_target_ops (&win32_target_ops);
ed50f18f
PA
1194 if (the_low_target.breakpoint != NULL)
1195 set_breakpoint_data (the_low_target.breakpoint,
1196 the_low_target.breakpoint_len);
b80864fb
DJ
1197 init_registers ();
1198}
This page took 0.109927 seconds and 4 git commands to generate.