3 Copyright 2000, 2002 Red Hat, Inc.
5 This file is part of RDA, the Red Hat Debug Agent (and library).
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
22 Alternative licenses for RDA may be arranged by contacting Red Hat,
34 #error The windows.h header is required when compiling for a Win32 target.
37 #include <sys/cygwin.h>
46 EXCEPTION_ACCESS_VIOLATION, "EXCEPTION_ACCESS_VIOLATION", SIGSEGV,
47 EXCEPTION_ARRAY_BOUNDS_EXCEEDED, "EXCEPTION_ARRAY_BOUNDS_EXCEEDED", SIGSEGV,
48 EXCEPTION_BREAKPOINT, "EXCEPTION_BREAKPOINT", SIGTRAP,
49 EXCEPTION_DATATYPE_MISALIGNMENT, "EXCEPTION_DATATYPE_MISALIGNMENT", SIGBUS,
50 EXCEPTION_FLT_DENORMAL_OPERAND, "EXCEPTION_FLT_DENORMAL_OPERAND", SIGFPE,
51 EXCEPTION_FLT_DIVIDE_BY_ZERO, "EXCEPTION_FLT_DIVIDE_BY_ZERO", SIGFPE,
52 EXCEPTION_FLT_INEXACT_RESULT, "EXCEPTION_FLT_INEXACT_RESULT", SIGFPE,
53 EXCEPTION_FLT_INVALID_OPERATION, "EXCEPTION_FLT_INVALID_OPERATION", SIGILL,
54 EXCEPTION_FLT_OVERFLOW, "EXCEPTION_FLT_OVERFLOW", SIGFPE,
55 EXCEPTION_FLT_STACK_CHECK, "EXCEPTION_FLT_STACK_CHECK", SIGFPE,
56 EXCEPTION_FLT_UNDERFLOW, "EXCEPTION_FLT_UNDERFLOW", SIGFPE,
57 EXCEPTION_ILLEGAL_INSTRUCTION, "EXCEPTION_ILLEGAL_INSTRUCTION", SIGILL,
58 EXCEPTION_IN_PAGE_ERROR, "EXCEPTION_IN_PAGE_ERROR", SIGSEGV,
59 EXCEPTION_INT_DIVIDE_BY_ZERO, "EXCEPTION_INT_DIVIDE_BY_ZERO", SIGFPE,
60 EXCEPTION_INT_OVERFLOW, "EXCEPTION_INT_OVERFLOW", SIGFPE,
61 EXCEPTION_INVALID_DISPOSITION, "EXCEPTION_INVALID_DISPOSITION", SIGILL,
62 EXCEPTION_NONCONTINUABLE_EXCEPTION,
63 "EXCEPTION_NONCONTINUABLE_EXCEPTION",SIGILL,
64 EXCEPTION_PRIV_INSTRUCTION, "EXCEPTION_PRIV_INSTRUCTION", SIGILL,
65 EXCEPTION_SINGLE_STEP, "EXCEPTION_SINGLE_STEP", SIGTRAP,
66 EXCEPTION_STACK_OVERFLOW, "EXCEPTION_STACK_OVERFLOW", SIGSEGV,
67 DBG_CONTROL_C, "DBG_CONTROL_C", SIGINT,
68 0, "Unknown exception", SIGUSR1
71 /* Debug output method similar to fprintf. */
73 child_process::debug (const char *format, ...)
80 va_start (ap, format);
81 vfprintf (stderr, format, ap);
86 child_process::handle_exception (DEBUG_EVENT &ev)
88 DWORD exc_code = ev.u.Exception.ExceptionRecord.ExceptionCode;
89 DWORD exc_flag = ev.u.Exception.ExceptionRecord.ExceptionFlags;
92 for (i = 0; sigmap[i].exc && sigmap[i].exc != exc_code; ++i)
95 debug ("Win32: Got exception 0x%08x = \"%s\", mapped to signal %d\n",
96 exc_code, sigmap[i].exc_txt, sigmap[i].sig);
98 if (exc_flag == EXCEPTION_NONCONTINUABLE)
99 set_term (sigmap[i].sig);
101 set_break (sigmap[i].sig);
104 /* fetch registers vector. */
106 child_process::fetch_regs ()
110 HANDLE thread_hdl = threads[cur_thread_id];
111 suspend_cnt = SuspendThread (thread_hdl) + 1;
112 context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
113 GetThreadContext (thread_hdl, &context);
118 child_process::store_regs ()
120 SetThreadContext (threads[cur_thread_id], &context);
124 child_process::resume_program (BOOL step)
129 context.EFlags |= FLAG_TRACE_BIT;
133 if (ContinueDebugEvent (cur_process_id,
135 stop_signal () && stop_signal () != SIGTRAP
136 ? DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE))
140 for (i = 0; i < suspend_cnt; ++i)
141 ResumeThread (threads[cur_thread_id]);
150 child_process::load_dll_event (DEBUG_EVENT &ev)
159 if (ev.dwProcessId == process_id
160 && ev.u.LoadDll.lpImageName
161 && ReadProcessMemory (process_hdl, ev.u.LoadDll.lpImageName,
162 &ptr, sizeof ptr, &processed)
164 && ReadProcessMemory (process_hdl, ptr,
165 buf, sizeof buf, &processed))
169 if (ev.u.LoadDll.fUnicode)
171 name = (char *) alloca (256);
172 WideCharToMultiByte (CP_ACP, 0, (const WCHAR *) buf, -1,
173 name, 256, NULL, NULL);
175 debug ("Win32: Load DLL \"%s\"\n", name);
178 debug ("Win32: Load DLL\n");
182 child_process::create_child ()
184 char real_path[PATH_MAX];
190 PROCESS_INFORMATION pi;
195 memset (&si, 0, sizeof (si));
198 cygwin_conv_to_win32_path (executable, real_path);
200 flags = DEBUG_ONLY_THIS_PROCESS;
203 flags |= CREATE_NEW_PROCESS_GROUP;
206 flags |= CREATE_NEW_CONSOLE;
208 len = strlen (real_path);
209 for (i = 1; i < argc; ++i)
210 len += strlen (argv[i]) + 1;
212 args = (char *) alloca (len + 2);
214 strcpy (args, real_path);
216 for (i = 1; i < argc; ++i)
219 strcat (args, argv[i]);
222 SetConsoleCtrlHandler (NULL, 0);
223 ret = CreateProcess (0,
224 args, /* command line */
227 TRUE, /* inherit handles */
228 flags, /* start flags */
230 NULL, /* current directory */
236 process_id = pi.dwProcessId;
242 child_process::check_state ()
244 static DEBUG_EVENT ev;
247 SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
250 if (!WaitForDebugEvent (&ev, 1000))
255 cur_process_id = ev.dwProcessId;
256 cur_thread_id = ev.dwThreadId;
260 switch (ev.dwDebugEventCode)
262 case CREATE_PROCESS_DEBUG_EVENT:
263 if (ev.dwProcessId != process_id)
265 debug ("Win32: Inferior process created\n");
270 debug ("Win32: A child process was created\n");
271 process_hdl = ev.u.CreateProcessInfo.hProcess;
275 case CREATE_THREAD_DEBUG_EVENT:
276 debug ("Win32: Create Thread\n");
277 if (ev.dwProcessId == process_id)
281 case LOAD_DLL_DEBUG_EVENT:
285 case UNLOAD_DLL_DEBUG_EVENT:
286 debug ("Win32: Unload DLL\n");
289 case OUTPUT_DEBUG_STRING_EVENT:
290 debug ("Win32: OutputDebugString\n");
291 if (ev.dwProcessId == process_id
292 && win32_output_debug_string (this, ev))
296 case EXIT_PROCESS_DEBUG_EVENT:
297 if (ev.dwProcessId == process_id)
299 debug ("Win32: Inferior exited with retcode = %d\n",
300 ev.u.ExitProcess.dwExitCode);
301 set_exit (ev.u.ExitProcess.dwExitCode);
305 debug ("Win32: Some child exited with retcode = %d\n",
306 ev.u.ExitProcess.dwExitCode);
309 case EXIT_THREAD_DEBUG_EVENT:
310 debug ("Win32: Thread exited with retcode = %d\n",
311 ev.u.ExitThread.dwExitCode);
313 /* What to return??? */
316 case EXCEPTION_DEBUG_EVENT:
317 handle_exception (ev);
321 if (!resume_program (FALSE))
330 child_process::fromtarget_break ()
332 debug ("Win32: from_target break\n");
333 gdbserv_fromtarget_break (serv, stop_signal ());
337 child_process::fromtarget_exit ()
339 debug ("Win32: from_target exit\n");
340 gdbserv_fromtarget_exit (serv, exit_code ());
344 child_process::fromtarget_terminate ()
346 debug ("Win32: from_target terminate\n");
347 gdbserv_fromtarget_terminate (serv, term_signal ());