1 /* Low level interface to Windows debugging, for gdbserver.
2 Copyright (C) 2006, 2007 Free Software Foundation, Inc.
4 Contributed by Leo Zayas. Based on "win32-nat.c" from GDB.
6 This file is part of GDB.
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.
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.
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. */
25 #include "gdb/signals.h"
30 #include <sys/param.h>
35 #include <sys/cygwin.h>
40 #define OUTMSG(X) do { printf X; fflush (stdout); } while (0)
42 #define OUTMSG2(X) do { printf X; fflush (stdout); } while (0)
47 int using_threads
= 1;
50 static HANDLE current_process_handle
= NULL
;
51 static DWORD current_process_id
= 0;
52 static enum target_signal last_sig
= TARGET_SIGNAL_0
;
54 /* The current debug event from WaitForDebugEvent. */
55 static DEBUG_EVENT current_event
;
57 static int debug_registers_changed
= 0;
58 static int debug_registers_used
= 0;
59 static unsigned dr
[8];
61 typedef BOOL
winapi_DebugActiveProcessStop (DWORD dwProcessId
);
62 typedef BOOL
winapi_DebugSetProcessKillOnExit (BOOL KillOnExit
);
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
69 /* Thread information structure used to track extra information about
71 typedef struct thread_info_struct
78 static DWORD main_thread_id
= 0;
80 /* Get the thread ID from the current selected inferior (the current
83 current_inferior_tid (void)
85 thread_info
*th
= inferior_target_data (current_inferior
);
89 /* Find a thread record given a thread id. If GET_CONTEXT is set then
90 also retrieve the context for this thread. */
92 thread_rec (DWORD id
, int get_context
)
94 struct thread_info
*thread
;
97 thread
= (struct thread_info
*) find_inferior_id (&all_threads
, id
);
101 th
= inferior_target_data (thread
);
102 if (!th
->suspend_count
&& get_context
)
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;
109 th
->context
.ContextFlags
= CONTEXT_DEBUGGER_DR
;
111 GetThreadContext (th
->h
, &th
->context
);
113 if (id
== current_event
.dwThreadId
)
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
;
128 /* Add a thread to the thread list. */
130 child_add_thread (DWORD tid
, HANDLE h
)
134 if ((th
= thread_rec (tid
, FALSE
)))
137 th
= (thread_info
*) malloc (sizeof (*th
));
138 memset (th
, 0, sizeof (*th
));
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 ());
147 /* Set the debug registers for the new thread if they are used. */
148 if (debug_registers_used
)
150 /* Only change the value of the debug registers. */
151 th
->context
.ContextFlags
= CONTEXT_DEBUGGER_DR
;
153 GetThreadContext (th
->h
, &th
->context
);
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;
169 /* Delete a thread from the list of threads. */
171 delete_thread_info (struct inferior_list_entry
*thread
)
173 thread_info
*th
= inferior_target_data ((struct thread_info
*) thread
);
175 remove_thread ((struct thread_info
*) thread
);
180 /* Delete a thread from the list of threads. */
182 child_delete_thread (DWORD id
)
184 struct inferior_list_entry
*thread
;
186 /* If the last thread is exiting, just return. */
187 if (all_threads
.head
== all_threads
.tail
)
190 thread
= find_inferior_id (&all_threads
, id
);
194 delete_thread_info (thread
);
197 /* Transfer memory from/to the debugged process. */
199 child_xfer_memory (CORE_ADDR memaddr
, char *our
, int len
,
200 int write
, struct target_ops
*target
)
203 long addr
= (long) memaddr
;
207 WriteProcessMemory (current_process_handle
, (LPVOID
) addr
,
208 (LPCVOID
) our
, len
, &done
);
209 FlushInstructionCache (current_process_handle
, (LPCVOID
) addr
, len
);
213 ReadProcessMemory (current_process_handle
, (LPCVOID
) addr
, (LPVOID
) our
,
219 /* Generally, what has the program done? */
222 /* The program has exited. The exit status is in value.integer. */
223 TARGET_WAITKIND_EXITED
,
225 /* The program has stopped with a signal. Which signal is in
227 TARGET_WAITKIND_STOPPED
,
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
,
233 /* The program has exec'ed a new executable file. The new file's
234 pathname is pointed to by value.execd_pathname. */
236 TARGET_WAITKIND_EXECD
,
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
241 TARGET_WAITKIND_SPURIOUS
,
244 struct target_waitstatus
246 enum target_waitkind kind
;
248 /* Forked child pid, execd pathname, exit status or signal number. */
252 enum target_signal sig
;
254 char *execd_pathname
;
261 #define FCS_REGNUM 27
262 #define FOP_REGNUM 31
264 #define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
265 static 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
),
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]),
308 context_offset (ExtendedRegisters
[24])
311 #undef context_offset
313 /* Clear out any old thread list and reintialize it to a pristine
316 child_init_thread_list (void)
318 for_each_inferior (&all_threads
, delete_thread_info
);
322 do_initial_child_stuff (DWORD pid
)
326 last_sig
= TARGET_SIGNAL_0
;
328 debug_registers_changed
= 0;
329 debug_registers_used
= 0;
330 for (i
= 0; i
< sizeof (dr
) / sizeof (dr
[0]); i
++)
332 memset (¤t_event
, 0, sizeof (current_event
));
334 child_init_thread_list ();
337 /* Resume all artificially suspended threads if we are continuing
340 continue_one_thread (struct inferior_list_entry
*this_thread
, void *id_ptr
)
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
);
347 if ((thread_id
== -1 || thread_id
== th
->tid
)
348 && th
->suspend_count
)
350 for (i
= 0; i
< th
->suspend_count
; i
++)
351 (void) ResumeThread (th
->h
);
352 th
->suspend_count
= 0;
353 if (debug_registers_changed
)
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;
373 child_continue (DWORD continue_status
, int thread_id
)
377 res
= ContinueDebugEvent (current_event
.dwProcessId
,
378 current_event
.dwThreadId
, continue_status
);
381 find_inferior (&all_threads
, continue_one_thread
, &thread_id
);
383 debug_registers_changed
= 0;
387 /* Fetch register(s) from gdbserver regcache data. */
389 do_child_fetch_inferior_registers (thread_info
*th
, int r
)
391 char *context_offset
= ((char *) &th
->context
) + mappings
[r
];
395 l
= *((long *) context_offset
) & 0xffff;
396 supply_register (r
, (char *) &l
);
398 else if (r
== FOP_REGNUM
)
400 l
= (*((long *) context_offset
) >> 16) & ((1 << 11) - 1);
401 supply_register (r
, (char *) &l
);
404 supply_register (r
, context_offset
);
407 /* Fetch register(s) from the current thread context. */
409 child_fetch_inferior_registers (int r
)
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
);
416 for (regno
= 0; regno
< r
; regno
++)
417 do_child_fetch_inferior_registers (th
, regno
);
420 /* Get register from gdbserver regcache data. */
422 do_child_store_inferior_registers (thread_info
*th
, int r
)
424 collect_register (r
, ((char *) &th
->context
) + mappings
[r
]);
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. */
430 child_store_inferior_registers (int r
)
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
);
437 for (regno
= 0; regno
< r
; regno
++)
438 do_child_store_inferior_registers (th
, regno
);
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. */
448 win32_create_inferior (char *program
, char **program_args
)
451 char real_path
[MAXPATHLEN
];
452 char *orig_path
, *new_path
, *path_ptr
;
456 PROCESS_INFORMATION pi
;
464 error ("No executable specified, specify executable to debug.\n");
466 memset (&si
, 0, sizeof (si
));
469 flags
= DEBUG_PROCESS
| DEBUG_ONLY_THIS_PROCESS
;
473 path_ptr
= getenv ("PATH");
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);
482 cygwin_conv_to_win32_path (program
, real_path
);
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
++)
493 /* FIXME: Can we do better about quoting? How does Cygwin
496 strcat (args
, program_args
[argc
]);
498 OUTMSG2 (("Command line is %s\n", args
));
500 flags
|= CREATE_NEW_PROCESS_GROUP
;
502 ret
= CreateProcess (0, args
, /* command line */
505 TRUE
, /* inherit handles */
506 flags
, /* start flags */
507 winenv
, NULL
, /* current directory */
512 setenv ("PATH", orig_path
, 1);
517 error ("Error creating process %s, (error %d): %s\n", args
,
518 (int) GetLastError (), strerror (GetLastError ()));
522 OUTMSG2 (("Process created: %s\n", (char *) args
));
525 CloseHandle (pi
.hThread
);
527 current_process_handle
= pi
.hProcess
;
528 current_process_id
= pi
.dwProcessId
;
530 do_initial_child_stuff (current_process_id
);
532 return current_process_id
;
535 /* Attach to a running process.
536 PID is the process ID to attach to, specified by the user
537 or a higher layer. */
539 win32_attach (unsigned long pid
)
542 HMODULE kernel32
= LoadLibrary ("KERNEL32.DLL");
543 winapi_DebugActiveProcessStop
*DebugActiveProcessStop
= NULL
;
544 winapi_DebugSetProcessKillOnExit
*DebugSetProcessKillOnExit
= NULL
;
546 DebugActiveProcessStop
=
547 (winapi_DebugActiveProcessStop
*) GetProcAddress (kernel32
,
548 "DebugActiveProcessStop");
549 DebugSetProcessKillOnExit
=
550 (winapi_DebugSetProcessKillOnExit
*) GetProcAddress (kernel32
,
551 "DebugSetProcessKillOnExit");
553 res
= DebugActiveProcess (pid
) ? 1 : 0;
556 error ("Attach to process failed.");
558 if (DebugSetProcessKillOnExit
!= NULL
)
559 DebugSetProcessKillOnExit (FALSE
);
561 current_process_id
= pid
;
562 current_process_handle
= OpenProcess (PROCESS_ALL_ACCESS
, FALSE
, pid
);
564 if (current_process_handle
== NULL
)
567 if (DebugActiveProcessStop
!= NULL
)
568 DebugActiveProcessStop (current_process_id
);
572 do_initial_child_stuff (pid
);
574 FreeLibrary (kernel32
);
579 /* Handle OUTPUT_DEBUG_STRING_EVENT from child process. */
581 handle_output_debug_string (struct target_waitstatus
*ourstatus
)
583 #define READ_BUFFER_LEN 1024
585 char s
[READ_BUFFER_LEN
+ 1] = { 0 };
586 DWORD nbytes
= current_event
.u
.DebugString
.nDebugStringLength
;
591 if (nbytes
> READ_BUFFER_LEN
)
592 nbytes
= READ_BUFFER_LEN
;
594 addr
= (CORE_ADDR
) (size_t) current_event
.u
.DebugString
.lpDebugStringData
;
596 if (current_event
.u
.DebugString
.fUnicode
)
598 /* The event tells us how many bytes, not chars, even
600 WCHAR buffer
[(READ_BUFFER_LEN
+ 1) / sizeof (WCHAR
)] = { 0 };
601 if (read_inferior_memory (addr
, (unsigned char *) buffer
, nbytes
) != 0)
603 wcstombs (s
, buffer
, (nbytes
+ 1) / sizeof (WCHAR
));
607 if (read_inferior_memory (addr
, (unsigned char *) s
, nbytes
) != 0)
611 if (strncmp (s
, "cYg", 3) != 0)
613 #undef READ_BUFFER_LEN
616 /* Kill all inferiors. */
620 if (current_process_handle
== NULL
)
623 TerminateProcess (current_process_handle
, 0);
626 if (!child_continue (DBG_CONTINUE
, -1))
628 if (!WaitForDebugEvent (¤t_event
, INFINITE
))
630 if (current_event
.dwDebugEventCode
== EXIT_PROCESS_DEBUG_EVENT
)
632 else if (current_event
.dwDebugEventCode
== OUTPUT_DEBUG_STRING_EVENT
)
634 struct target_waitstatus our_status
= { 0 };
635 handle_output_debug_string (&our_status
);
640 /* Detach from all inferiors. */
644 HMODULE kernel32
= LoadLibrary ("KERNEL32.DLL");
645 winapi_DebugActiveProcessStop
*DebugActiveProcessStop
= NULL
;
646 winapi_DebugSetProcessKillOnExit
*DebugSetProcessKillOnExit
= NULL
;
648 DebugActiveProcessStop
=
649 (winapi_DebugActiveProcessStop
*) GetProcAddress (kernel32
,
650 "DebugActiveProcessStop");
651 DebugSetProcessKillOnExit
=
652 (winapi_DebugSetProcessKillOnExit
*) GetProcAddress (kernel32
,
653 "DebugSetProcessKillOnExit");
655 if (DebugSetProcessKillOnExit
!= NULL
)
656 DebugSetProcessKillOnExit (FALSE
);
658 if (DebugActiveProcessStop
!= NULL
)
659 DebugActiveProcessStop (current_process_id
);
663 FreeLibrary (kernel32
);
666 /* Return 1 iff the thread with thread ID TID is alive. */
668 win32_thread_alive (unsigned long tid
)
672 /* Our thread list is reliable; don't bother to poll target
674 if (find_inferior_id (&all_threads
, tid
) != NULL
)
681 /* Resume the inferior process. RESUME_INFO describes how we want
684 win32_resume (struct thread_resume
*resume_info
)
687 enum target_signal sig
;
690 DWORD continue_status
= DBG_CONTINUE
;
692 /* This handles the very limited set of resume packets that GDB can
693 currently produce. */
695 if (resume_info
[0].thread
== -1)
697 else if (resume_info
[1].thread
== -1 && !resume_info
[1].leave_stopped
)
700 /* Yes, we're ignoring resume_info[0].thread. It'd be tricky to make
701 the Windows resume code do the right thing for thread switching. */
702 tid
= current_event
.dwThreadId
;
704 if (resume_info
[0].thread
!= -1)
706 sig
= resume_info
[0].sig
;
707 step
= resume_info
[0].step
;
715 if (sig
!= TARGET_SIGNAL_0
)
717 if (current_event
.dwDebugEventCode
!= EXCEPTION_DEBUG_EVENT
)
719 OUTMSG (("Cannot continue with signal %d here.\n", sig
));
721 else if (sig
== last_sig
)
722 continue_status
= DBG_EXCEPTION_NOT_HANDLED
;
724 OUTMSG (("Can only continue with recieved signal %d.\n", last_sig
));
727 last_sig
= TARGET_SIGNAL_0
;
729 /* Get context for the currently selected thread. */
730 th
= thread_rec (current_event
.dwThreadId
, FALSE
);
733 if (th
->context
.ContextFlags
)
735 if (debug_registers_changed
)
737 th
->context
.Dr0
= dr
[0];
738 th
->context
.Dr1
= dr
[1];
739 th
->context
.Dr2
= dr
[2];
740 th
->context
.Dr3
= dr
[3];
741 /* th->context.Dr6 = dr[6];
742 FIXME: should we set dr6 also ?? */
743 th
->context
.Dr7
= dr
[7];
746 /* Move register values from the inferior into the thread
747 context structure. */
748 regcache_invalidate ();
751 th
->context
.EFlags
|= FLAG_TRACE_BIT
;
753 SetThreadContext (th
->h
, &th
->context
);
754 th
->context
.ContextFlags
= 0;
758 /* Allow continuing with the same signal that interrupted us.
759 Otherwise complain. */
761 child_continue (continue_status
, tid
);
765 handle_exception (struct target_waitstatus
*ourstatus
)
768 DWORD code
= current_event
.u
.Exception
.ExceptionRecord
.ExceptionCode
;
770 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
772 /* Record the context of the current thread. */
773 th
= thread_rec (current_event
.dwThreadId
, -1);
777 case EXCEPTION_ACCESS_VIOLATION
:
778 OUTMSG2 (("EXCEPTION_ACCESS_VIOLATION"));
779 ourstatus
->value
.sig
= TARGET_SIGNAL_SEGV
;
781 case STATUS_STACK_OVERFLOW
:
782 OUTMSG2 (("STATUS_STACK_OVERFLOW"));
783 ourstatus
->value
.sig
= TARGET_SIGNAL_SEGV
;
785 case STATUS_FLOAT_DENORMAL_OPERAND
:
786 OUTMSG2 (("STATUS_FLOAT_DENORMAL_OPERAND"));
787 ourstatus
->value
.sig
= TARGET_SIGNAL_FPE
;
789 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
790 OUTMSG2 (("EXCEPTION_ARRAY_BOUNDS_EXCEEDED"));
791 ourstatus
->value
.sig
= TARGET_SIGNAL_FPE
;
793 case STATUS_FLOAT_INEXACT_RESULT
:
794 OUTMSG2 (("STATUS_FLOAT_INEXACT_RESULT"));
795 ourstatus
->value
.sig
= TARGET_SIGNAL_FPE
;
797 case STATUS_FLOAT_INVALID_OPERATION
:
798 OUTMSG2 (("STATUS_FLOAT_INVALID_OPERATION"));
799 ourstatus
->value
.sig
= TARGET_SIGNAL_FPE
;
801 case STATUS_FLOAT_OVERFLOW
:
802 OUTMSG2 (("STATUS_FLOAT_OVERFLOW"));
803 ourstatus
->value
.sig
= TARGET_SIGNAL_FPE
;
805 case STATUS_FLOAT_STACK_CHECK
:
806 OUTMSG2 (("STATUS_FLOAT_STACK_CHECK"));
807 ourstatus
->value
.sig
= TARGET_SIGNAL_FPE
;
809 case STATUS_FLOAT_UNDERFLOW
:
810 OUTMSG2 (("STATUS_FLOAT_UNDERFLOW"));
811 ourstatus
->value
.sig
= TARGET_SIGNAL_FPE
;
813 case STATUS_FLOAT_DIVIDE_BY_ZERO
:
814 OUTMSG2 (("STATUS_FLOAT_DIVIDE_BY_ZERO"));
815 ourstatus
->value
.sig
= TARGET_SIGNAL_FPE
;
817 case STATUS_INTEGER_DIVIDE_BY_ZERO
:
818 OUTMSG2 (("STATUS_INTEGER_DIVIDE_BY_ZERO"));
819 ourstatus
->value
.sig
= TARGET_SIGNAL_FPE
;
821 case STATUS_INTEGER_OVERFLOW
:
822 OUTMSG2 (("STATUS_INTEGER_OVERFLOW"));
823 ourstatus
->value
.sig
= TARGET_SIGNAL_FPE
;
825 case EXCEPTION_BREAKPOINT
:
826 OUTMSG2 (("EXCEPTION_BREAKPOINT"));
827 ourstatus
->value
.sig
= TARGET_SIGNAL_TRAP
;
830 OUTMSG2 (("DBG_CONTROL_C"));
831 ourstatus
->value
.sig
= TARGET_SIGNAL_INT
;
833 case DBG_CONTROL_BREAK
:
834 OUTMSG2 (("DBG_CONTROL_BREAK"));
835 ourstatus
->value
.sig
= TARGET_SIGNAL_INT
;
837 case EXCEPTION_SINGLE_STEP
:
838 OUTMSG2 (("EXCEPTION_SINGLE_STEP"));
839 ourstatus
->value
.sig
= TARGET_SIGNAL_TRAP
;
841 case EXCEPTION_ILLEGAL_INSTRUCTION
:
842 OUTMSG2 (("EXCEPTION_ILLEGAL_INSTRUCTION"));
843 ourstatus
->value
.sig
= TARGET_SIGNAL_ILL
;
845 case EXCEPTION_PRIV_INSTRUCTION
:
846 OUTMSG2 (("EXCEPTION_PRIV_INSTRUCTION"));
847 ourstatus
->value
.sig
= TARGET_SIGNAL_ILL
;
849 case EXCEPTION_NONCONTINUABLE_EXCEPTION
:
850 OUTMSG2 (("EXCEPTION_NONCONTINUABLE_EXCEPTION"));
851 ourstatus
->value
.sig
= TARGET_SIGNAL_ILL
;
854 if (current_event
.u
.Exception
.dwFirstChance
)
856 OUTMSG2 (("gdbserver: unknown target exception 0x%08lx at 0x%08lx",
857 current_event
.u
.Exception
.ExceptionRecord
.ExceptionCode
,
858 (DWORD
) current_event
.u
.Exception
.ExceptionRecord
.
860 ourstatus
->value
.sig
= TARGET_SIGNAL_UNKNOWN
;
864 last_sig
= ourstatus
->value
.sig
;
868 /* Get the next event from the child. Return 1 if the event requires
871 get_child_debug_event (struct target_waitstatus
*ourstatus
)
874 DWORD continue_status
, event_code
;
875 thread_info
*th
= NULL
;
876 static thread_info dummy_thread_info
;
881 last_sig
= TARGET_SIGNAL_0
;
882 ourstatus
->kind
= TARGET_WAITKIND_SPURIOUS
;
884 if (!(debug_event
= WaitForDebugEvent (¤t_event
, 1000)))
888 (struct thread_info
*) find_inferior_id (&all_threads
,
889 current_event
.dwThreadId
);
891 continue_status
= DBG_CONTINUE
;
892 event_code
= current_event
.dwDebugEventCode
;
896 case CREATE_THREAD_DEBUG_EVENT
:
897 OUTMSG2 (("gdbserver: kernel event CREATE_THREAD_DEBUG_EVENT "
898 "for pid=%d tid=%x)\n",
899 (unsigned) current_event
.dwProcessId
,
900 (unsigned) current_event
.dwThreadId
));
902 /* Record the existence of this thread. */
903 th
= child_add_thread (current_event
.dwThreadId
,
904 current_event
.u
.CreateThread
.hThread
);
906 retval
= current_event
.dwThreadId
;
909 case EXIT_THREAD_DEBUG_EVENT
:
910 OUTMSG2 (("gdbserver: kernel event EXIT_THREAD_DEBUG_EVENT "
911 "for pid=%d tid=%x\n",
912 (unsigned) current_event
.dwProcessId
,
913 (unsigned) current_event
.dwThreadId
));
914 child_delete_thread (current_event
.dwThreadId
);
915 th
= &dummy_thread_info
;
918 case CREATE_PROCESS_DEBUG_EVENT
:
919 OUTMSG2 (("gdbserver: kernel event CREATE_PROCESS_DEBUG_EVENT "
920 "for pid=%d tid=%x\n",
921 (unsigned) current_event
.dwProcessId
,
922 (unsigned) current_event
.dwThreadId
));
923 CloseHandle (current_event
.u
.CreateProcessInfo
.hFile
);
925 current_process_handle
= current_event
.u
.CreateProcessInfo
.hProcess
;
926 main_thread_id
= current_event
.dwThreadId
;
928 ourstatus
->kind
= TARGET_WAITKIND_EXECD
;
929 ourstatus
->value
.execd_pathname
= "Main executable";
931 /* Add the main thread. */
933 child_add_thread (main_thread_id
,
934 current_event
.u
.CreateProcessInfo
.hThread
);
936 retval
= ourstatus
->value
.related_pid
= current_event
.dwThreadId
;
939 case EXIT_PROCESS_DEBUG_EVENT
:
940 OUTMSG2 (("gdbserver: kernel event EXIT_PROCESS_DEBUG_EVENT "
941 "for pid=%d tid=%x\n",
942 (unsigned) current_event
.dwProcessId
,
943 (unsigned) current_event
.dwThreadId
));
944 ourstatus
->kind
= TARGET_WAITKIND_EXITED
;
945 ourstatus
->value
.integer
= current_event
.u
.ExitProcess
.dwExitCode
;
946 CloseHandle (current_process_handle
);
947 current_process_handle
= NULL
;
948 retval
= main_thread_id
;
951 case LOAD_DLL_DEBUG_EVENT
:
952 OUTMSG2 (("gdbserver: kernel event LOAD_DLL_DEBUG_EVENT "
953 "for pid=%d tid=%x\n",
954 (unsigned) current_event
.dwProcessId
,
955 (unsigned) current_event
.dwThreadId
));
956 CloseHandle (current_event
.u
.LoadDll
.hFile
);
958 ourstatus
->kind
= TARGET_WAITKIND_LOADED
;
959 ourstatus
->value
.integer
= 0;
960 retval
= main_thread_id
;
963 case UNLOAD_DLL_DEBUG_EVENT
:
964 OUTMSG2 (("gdbserver: kernel event UNLOAD_DLL_DEBUG_EVENT "
965 "for pid=%d tid=%x\n",
966 (unsigned) current_event
.dwProcessId
,
967 (unsigned) current_event
.dwThreadId
));
970 case EXCEPTION_DEBUG_EVENT
:
971 OUTMSG2 (("gdbserver: kernel event EXCEPTION_DEBUG_EVENT "
972 "for pid=%d tid=%x\n",
973 (unsigned) current_event
.dwProcessId
,
974 (unsigned) current_event
.dwThreadId
));
975 retval
= handle_exception (ourstatus
);
978 case OUTPUT_DEBUG_STRING_EVENT
:
979 /* A message from the kernel (or Cygwin). */
980 OUTMSG2 (("gdbserver: kernel event OUTPUT_DEBUG_STRING_EVENT "
981 "for pid=%d tid=%x\n",
982 (unsigned) current_event
.dwProcessId
,
983 (unsigned) current_event
.dwThreadId
));
984 handle_output_debug_string (ourstatus
);
988 OUTMSG2 (("gdbserver: kernel event unknown "
989 "for pid=%d tid=%x code=%ld\n",
990 (unsigned) current_event
.dwProcessId
,
991 (unsigned) current_event
.dwThreadId
,
992 current_event
.dwDebugEventCode
));
997 (struct thread_info
*) find_inferior_id (&all_threads
,
998 current_event
.dwThreadId
);
1000 if (!retval
|| (event_code
!= EXCEPTION_DEBUG_EVENT
&& event_code
!= EXIT_PROCESS_DEBUG_EVENT
))
1002 child_continue (continue_status
, -1);
1007 thread_rec (current_event
.dwThreadId
, TRUE
);
1013 /* Wait for the inferior process to change state.
1014 STATUS will be filled in with a response code to send to GDB.
1015 Returns the signal which caused the process to stop. */
1016 static unsigned char
1017 win32_wait (char *status
)
1019 struct target_waitstatus our_status
;
1025 get_child_debug_event (&our_status
);
1027 if (our_status
.kind
== TARGET_WAITKIND_EXITED
)
1029 OUTMSG2 (("Child exited with retcode = %x\n",
1030 our_status
.value
.integer
));
1034 child_fetch_inferior_registers (-1);
1036 return our_status
.value
.integer
;
1038 else if (our_status
.kind
== TARGET_WAITKIND_STOPPED
)
1040 OUTMSG2 (("Child Stopped with signal = %x \n",
1041 WSTOPSIG (our_status
.value
.sig
)));
1045 child_fetch_inferior_registers (-1);
1047 return our_status
.value
.sig
;
1050 OUTMSG (("Ignoring unknown internal event, %d\n", our_status
.kind
));
1053 struct thread_resume resume
;
1057 resume
.leave_stopped
= 0;
1058 win32_resume (&resume
);
1063 /* Fetch registers from the inferior process.
1064 If REGNO is -1, fetch all registers; otherwise, fetch at least REGNO. */
1066 win32_fetch_inferior_registers (int regno
)
1068 child_fetch_inferior_registers (regno
);
1071 /* Store registers to the inferior process.
1072 If REGNO is -1, store all registers; otherwise, store at least REGNO. */
1074 win32_store_inferior_registers (int regno
)
1076 child_store_inferior_registers (regno
);
1079 /* Read memory from the inferior process. This should generally be
1080 called through read_inferior_memory, which handles breakpoint shadowing.
1081 Read LEN bytes at MEMADDR into a buffer at MYADDR. */
1083 win32_read_inferior_memory (CORE_ADDR memaddr
, unsigned char *myaddr
, int len
)
1085 return child_xfer_memory (memaddr
, myaddr
, len
, 0, 0) != len
;
1088 /* Write memory to the inferior process. This should generally be
1089 called through write_inferior_memory, which handles breakpoint shadowing.
1090 Write LEN bytes from the buffer at MYADDR to MEMADDR.
1091 Returns 0 on success and errno on failure. */
1093 win32_write_inferior_memory (CORE_ADDR memaddr
, const unsigned char *myaddr
,
1096 return child_xfer_memory (memaddr
, (char *) myaddr
, len
, 1, 0) != len
;
1100 win32_arch_string (void)
1105 static struct target_ops win32_target_ops
= {
1106 win32_create_inferior
,
1113 win32_fetch_inferior_registers
,
1114 win32_store_inferior_registers
,
1115 win32_read_inferior_memory
,
1116 win32_write_inferior_memory
,
1129 /* Initialize the Win32 backend. */
1131 initialize_low (void)
1133 set_target_ops (&win32_target_ops
);