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