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