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