1 /* Target-vector operations for controlling win32 child processes, for GDB.
2 Copyright 1995, 1996 Free Software Foundation, Inc.
3 Contributed by Cygnus Support.
5 This file is part of GDB.
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 eve nthe 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, Boston, MA 02111-1307, USA. */
23 /* We assume we're being built with and will be used for cygwin32. */
26 #include "frame.h" /* required by inferior.h */
33 #include <sys/types.h>
39 #include "gdb_string.h"
40 #include "gdbthread.h"
42 #include <sys/param.h>
45 #define CHECK(x) check (x, __FILE__,__LINE__)
46 #define DEBUG_EXEC(x) if (debug_exec) printf x
47 #define DEBUG_EVENTS(x) if (debug_events) printf x
48 #define DEBUG_MEM(x) if (debug_memory) printf x
49 #define DEBUG_EXCEPT(x) if (debug_exceptions) printf x
51 /* Forward declaration */
52 extern struct target_ops child_ops;
54 static void child_stop PARAMS ((void));
56 /* The most recently read context. Inspect ContextFlags to see what
59 static CONTEXT context;
61 /* The process and thread handles for the above context. */
63 static HANDLE current_process;
64 static HANDLE current_thread;
65 static int current_process_id;
66 static int current_thread_id;
68 /* Counts of things. */
69 static int exception_count = 0;
70 static int event_count = 0;
73 static int new_console = 0;
74 static int new_group = 0;
75 static int debug_exec = 0; /* show execution */
76 static int debug_events = 0; /* show events from kernel */
77 static int debug_memory = 0; /* show target memory accesses */
78 static int debug_exceptions = 0; /* show target exceptions */
80 /* This vector maps GDB's idea of a register's number into an address
81 in the win32 exception context vector.
83 It also contains the bit mask needed to load the register in question.
85 One day we could read a reg, we could inspect the context we
86 already have loaded, if it doesn't have the bit set that we need,
87 we read that set of registers in using GetThreadContext. If the
88 context already contains what we need, we just unpack it. Then to
89 write a register, first we have to ensure that the context contains
90 the other regs of the group, and then we copy the info in and set
100 static const struct regmappings mappings[] =
103 {(char *) &context.Gpr0, CONTEXT_INTEGER},
104 {(char *) &context.Gpr1, CONTEXT_INTEGER},
105 {(char *) &context.Gpr2, CONTEXT_INTEGER},
106 {(char *) &context.Gpr3, CONTEXT_INTEGER},
107 {(char *) &context.Gpr4, CONTEXT_INTEGER},
108 {(char *) &context.Gpr5, CONTEXT_INTEGER},
109 {(char *) &context.Gpr6, CONTEXT_INTEGER},
110 {(char *) &context.Gpr7, CONTEXT_INTEGER},
112 {(char *) &context.Gpr8, CONTEXT_INTEGER},
113 {(char *) &context.Gpr9, CONTEXT_INTEGER},
114 {(char *) &context.Gpr10, CONTEXT_INTEGER},
115 {(char *) &context.Gpr11, CONTEXT_INTEGER},
116 {(char *) &context.Gpr12, CONTEXT_INTEGER},
117 {(char *) &context.Gpr13, CONTEXT_INTEGER},
118 {(char *) &context.Gpr14, CONTEXT_INTEGER},
119 {(char *) &context.Gpr15, CONTEXT_INTEGER},
121 {(char *) &context.Gpr16, CONTEXT_INTEGER},
122 {(char *) &context.Gpr17, CONTEXT_INTEGER},
123 {(char *) &context.Gpr18, CONTEXT_INTEGER},
124 {(char *) &context.Gpr19, CONTEXT_INTEGER},
125 {(char *) &context.Gpr20, CONTEXT_INTEGER},
126 {(char *) &context.Gpr21, CONTEXT_INTEGER},
127 {(char *) &context.Gpr22, CONTEXT_INTEGER},
128 {(char *) &context.Gpr23, CONTEXT_INTEGER},
130 {(char *) &context.Gpr24, CONTEXT_INTEGER},
131 {(char *) &context.Gpr25, CONTEXT_INTEGER},
132 {(char *) &context.Gpr26, CONTEXT_INTEGER},
133 {(char *) &context.Gpr27, CONTEXT_INTEGER},
134 {(char *) &context.Gpr28, CONTEXT_INTEGER},
135 {(char *) &context.Gpr29, CONTEXT_INTEGER},
136 {(char *) &context.Gpr30, CONTEXT_INTEGER},
137 {(char *) &context.Gpr31, CONTEXT_INTEGER},
139 {(char *) &context.Fpr0, CONTEXT_FLOATING_POINT},
140 {(char *) &context.Fpr1, CONTEXT_FLOATING_POINT},
141 {(char *) &context.Fpr2, CONTEXT_FLOATING_POINT},
142 {(char *) &context.Fpr3, CONTEXT_FLOATING_POINT},
143 {(char *) &context.Fpr4, CONTEXT_FLOATING_POINT},
144 {(char *) &context.Fpr5, CONTEXT_FLOATING_POINT},
145 {(char *) &context.Fpr6, CONTEXT_FLOATING_POINT},
146 {(char *) &context.Fpr7, CONTEXT_FLOATING_POINT},
148 {(char *) &context.Fpr8, CONTEXT_FLOATING_POINT},
149 {(char *) &context.Fpr9, CONTEXT_FLOATING_POINT},
150 {(char *) &context.Fpr10, CONTEXT_FLOATING_POINT},
151 {(char *) &context.Fpr11, CONTEXT_FLOATING_POINT},
152 {(char *) &context.Fpr12, CONTEXT_FLOATING_POINT},
153 {(char *) &context.Fpr13, CONTEXT_FLOATING_POINT},
154 {(char *) &context.Fpr14, CONTEXT_FLOATING_POINT},
155 {(char *) &context.Fpr15, CONTEXT_FLOATING_POINT},
157 {(char *) &context.Fpr16, CONTEXT_FLOATING_POINT},
158 {(char *) &context.Fpr17, CONTEXT_FLOATING_POINT},
159 {(char *) &context.Fpr18, CONTEXT_FLOATING_POINT},
160 {(char *) &context.Fpr19, CONTEXT_FLOATING_POINT},
161 {(char *) &context.Fpr20, CONTEXT_FLOATING_POINT},
162 {(char *) &context.Fpr21, CONTEXT_FLOATING_POINT},
163 {(char *) &context.Fpr22, CONTEXT_FLOATING_POINT},
164 {(char *) &context.Fpr23, CONTEXT_FLOATING_POINT},
166 {(char *) &context.Fpr24, CONTEXT_FLOATING_POINT},
167 {(char *) &context.Fpr25, CONTEXT_FLOATING_POINT},
168 {(char *) &context.Fpr26, CONTEXT_FLOATING_POINT},
169 {(char *) &context.Fpr27, CONTEXT_FLOATING_POINT},
170 {(char *) &context.Fpr28, CONTEXT_FLOATING_POINT},
171 {(char *) &context.Fpr29, CONTEXT_FLOATING_POINT},
172 {(char *) &context.Fpr30, CONTEXT_FLOATING_POINT},
173 {(char *) &context.Fpr31, CONTEXT_FLOATING_POINT},
176 {(char *) &context.Iar, CONTEXT_CONTROL},
177 {(char *) &context.Msr, CONTEXT_CONTROL},
178 {(char *) &context.Cr, CONTEXT_INTEGER},
179 {(char *) &context.Lr, CONTEXT_CONTROL},
180 {(char *) &context.Ctr, CONTEXT_CONTROL},
182 {(char *) &context.Xer, CONTEXT_INTEGER},
183 {0,0}, /* MQ, but there isn't one */
185 {(char *) &context.Eax, CONTEXT_INTEGER},
186 {(char *) &context.Ecx, CONTEXT_INTEGER},
187 {(char *) &context.Edx, CONTEXT_INTEGER},
188 {(char *) &context.Ebx, CONTEXT_INTEGER},
189 {(char *) &context.Esp, CONTEXT_CONTROL},
190 {(char *) &context.Ebp, CONTEXT_CONTROL},
191 {(char *) &context.Esi, CONTEXT_INTEGER},
192 {(char *) &context.Edi, CONTEXT_INTEGER},
193 {(char *) &context.Eip, CONTEXT_CONTROL},
194 {(char *) &context.EFlags, CONTEXT_CONTROL},
195 {(char *) &context.SegCs, CONTEXT_SEGMENTS},
196 {(char *) &context.SegSs, CONTEXT_SEGMENTS},
197 {(char *) &context.SegDs, CONTEXT_SEGMENTS},
198 {(char *) &context.SegEs, CONTEXT_SEGMENTS},
199 {(char *) &context.SegFs, CONTEXT_SEGMENTS},
200 {(char *) &context.SegGs, CONTEXT_SEGMENTS},
201 {&context.FloatSave.RegisterArea[0 * 10], CONTEXT_FLOATING_POINT},
202 {&context.FloatSave.RegisterArea[1 * 10], CONTEXT_FLOATING_POINT},
203 {&context.FloatSave.RegisterArea[2 * 10], CONTEXT_FLOATING_POINT},
204 {&context.FloatSave.RegisterArea[3 * 10], CONTEXT_FLOATING_POINT},
205 {&context.FloatSave.RegisterArea[4 * 10], CONTEXT_FLOATING_POINT},
206 {&context.FloatSave.RegisterArea[5 * 10], CONTEXT_FLOATING_POINT},
207 {&context.FloatSave.RegisterArea[6 * 10], CONTEXT_FLOATING_POINT},
208 {&context.FloatSave.RegisterArea[7 * 10], CONTEXT_FLOATING_POINT},
213 /* This vector maps the target's idea of an exception (extracted
214 from the DEBUG_EVENT structure) to GDB's idea. */
216 struct xlate_exception
219 enum target_signal us;
223 static const struct xlate_exception
226 {EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV},
227 {STATUS_STACK_OVERFLOW, TARGET_SIGNAL_SEGV},
228 {EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP},
229 {DBG_CONTROL_C, TARGET_SIGNAL_INT},
230 {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP},
235 check (BOOL ok, const char *file, int line)
238 printf_filtered ("error return %s:%d was %d\n", file, line, GetLastError ());
242 child_fetch_inferior_registers (int r)
246 for (r = 0; r < NUM_REGS; r++)
247 child_fetch_inferior_registers (r);
251 supply_register (r, mappings[r].incontext);
256 child_store_inferior_registers (int r)
260 for (r = 0; r < NUM_REGS; r++)
261 child_store_inferior_registers (r);
265 read_register_gen (r, mappings[r].incontext);
270 /* Wait for child to do something. Return pid of child, or -1 in case
271 of error; store status through argument pointer OURSTATUS. */
275 handle_load_dll (char *eventp)
277 DEBUG_EVENT * event = (DEBUG_EVENT *)eventp;
281 ReadProcessMemory (current_process,
282 (DWORD) event->u.LoadDll.lpImageName,
283 (char *) &dll_name_ptr,
284 sizeof (dll_name_ptr), &done);
286 /* See if we could read the address of a string, and that the
287 address isn't null. */
289 if (done == sizeof (dll_name_ptr) && dll_name_ptr)
291 char *dll_name, *dll_basename;
292 struct objfile *objfile;
293 char unix_dll_name[MAX_PATH];
294 int size = event->u.LoadDll.fUnicode ? sizeof (WCHAR) : sizeof (char);
299 ReadProcessMemory (current_process,
300 dll_name_ptr + len * size,
306 while ((b[0] != 0 || b[size - 1] != 0) && done == size);
308 dll_name = alloca (len);
310 if (event->u.LoadDll.fUnicode)
312 WCHAR *unicode_dll_name = (WCHAR *) alloca (len * sizeof (WCHAR));
313 ReadProcessMemory (current_process,
316 len * sizeof (WCHAR),
319 WideCharToMultiByte (CP_ACP, 0,
320 unicode_dll_name, len,
321 dll_name, len, 0, 0);
325 ReadProcessMemory (current_process,
332 /* FIXME: Can we delete this call? */
333 cygwin32_conv_to_posix_path (dll_name, unix_dll_name);
335 /* FIXME!! It would be nice to define one symbol which pointed to the
336 front of the dll if we can't find any symbols. */
338 if (!(dll_basename = strrchr(dll_name, '\\')))
339 dll_basename = strrchr(dll_name, '/');
341 ALL_OBJFILES(objfile)
343 char *objfile_basename;
344 if (!(objfile_basename = strrchr(objfile->name, '\\')))
345 objfile_basename = strrchr(objfile->name, '/');
347 if (dll_basename && objfile_basename &&
348 strcmp(dll_basename+1, objfile_basename+1) == 0)
350 printf_unfiltered ("%s (symbols previously loaded)\n",
357 context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
358 GetThreadContext (current_thread, &context);
360 /* The symbols in a dll are offset by 0x1000, which is the
361 the offset from 0 of the first byte in an image - because
362 of the file header and the section alignment.
364 FIXME: Is this the real reason that we need the 0x1000 ? */
367 symbol_file_add (unix_dll_name, 0,
368 (int) event->u.LoadDll.lpBaseOfDll + 0x1000, 0, 0, 0);
370 printf_unfiltered ("%x:%s\n", event->u.LoadDll.lpBaseOfDll,
378 handle_exception (DEBUG_EVENT * event, struct target_waitstatus *ourstatus)
382 ourstatus->kind = TARGET_WAITKIND_STOPPED;
385 switch (event->u.Exception.ExceptionRecord.ExceptionCode)
387 case EXCEPTION_ACCESS_VIOLATION:
388 DEBUG_EXCEPT (("gdb: Target exception ACCESS_VIOLATION at 0x%08x\n",
389 event->u.Exception.ExceptionRecord.ExceptionAddress));
390 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
392 case STATUS_STACK_OVERFLOW:
393 DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08x\n",
394 event->u.Exception.ExceptionRecord.ExceptionAddress));
395 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
397 case EXCEPTION_BREAKPOINT:
398 DEBUG_EXCEPT (("gdb: Target exception BREAKPOINT at 0x%08x\n",
399 event->u.Exception.ExceptionRecord.ExceptionAddress));
400 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
403 DEBUG_EXCEPT (("gdb: Target exception CONTROL_C at 0x%08x\n",
404 event->u.Exception.ExceptionRecord.ExceptionAddress));
405 ourstatus->value.sig = TARGET_SIGNAL_INT;
407 case EXCEPTION_SINGLE_STEP:
408 DEBUG_EXCEPT (("gdb: Target exception SINGLE_STEP at 0x%08x\n",
409 event->u.Exception.ExceptionRecord.ExceptionAddress));
410 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
413 printf_unfiltered ("gdb: unknown target exception 0x%08x at 0x%08x\n",
414 event->u.Exception.ExceptionRecord.ExceptionCode,
415 event->u.Exception.ExceptionRecord.ExceptionAddress);
416 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
419 context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
420 GetThreadContext (current_thread, &context);
425 child_wait (int pid, struct target_waitstatus *ourstatus)
427 /* We loop when we get a non-standard exception rather than return
428 with a SPURIOUS because resume can try and step or modify things,
429 which needs a current_thread. But some of these exceptions mark
430 the birth or death of threads, which mean that the current thread
431 isn't necessarily what you think it is. */
436 BOOL t = WaitForDebugEvent (&event, INFINITE);
441 current_thread_id = event.dwThreadId;
442 current_process_id = event.dwProcessId;
444 switch (event.dwDebugEventCode)
446 case CREATE_THREAD_DEBUG_EVENT:
447 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
448 event.dwProcessId, event.dwThreadId,
449 "CREATE_THREAD_DEBUG_EVENT"));
451 case EXIT_THREAD_DEBUG_EVENT:
452 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
453 event.dwProcessId, event.dwThreadId,
454 "EXIT_THREAD_DEBUG_EVENT"));
456 case CREATE_PROCESS_DEBUG_EVENT:
457 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
458 event.dwProcessId, event.dwThreadId,
459 "CREATE_PROCESS_DEBUG_EVENT"));
462 case EXIT_PROCESS_DEBUG_EVENT:
463 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
464 event.dwProcessId, event.dwThreadId,
465 "EXIT_PROCESS_DEBUG_EVENT"));
466 ourstatus->kind = TARGET_WAITKIND_EXITED;
467 ourstatus->value.integer = event.u.ExitProcess.dwExitCode;
468 CloseHandle (current_process);
469 CloseHandle (current_thread);
470 return current_process_id;
473 case LOAD_DLL_DEBUG_EVENT:
474 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
475 event.dwProcessId, event.dwThreadId,
476 "LOAD_DLL_DEBUG_EVENT"));
477 catch_errors (handle_load_dll,
479 "\n[failed reading symbols from DLL]\n",
481 registers_changed(); /* mark all regs invalid */
483 case UNLOAD_DLL_DEBUG_EVENT:
484 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
485 event.dwProcessId, event.dwThreadId,
486 "UNLOAD_DLL_DEBUG_EVENT"));
487 break; /* FIXME: don't know what to do here */
488 case EXCEPTION_DEBUG_EVENT:
489 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
490 event.dwProcessId, event.dwThreadId,
491 "EXCEPTION_DEBUG_EVENT"));
492 handle_exception (&event, ourstatus);
493 return current_process_id;
495 case OUTPUT_DEBUG_STRING_EVENT: /* message from the kernel */
496 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
497 event.dwProcessId, event.dwThreadId,
498 "OUTPUT_DEBUG_STRING_EVENT"));
499 if (target_read_string
500 ((CORE_ADDR) event.u.DebugString.lpDebugStringData,
501 &p, 1024, 0) && p && *p)
508 printf_unfiltered ("gdb: kernel event for pid=%d tid=%d\n",
509 event.dwProcessId, event.dwThreadId);
510 printf_unfiltered (" unknown event code %d\n",
511 event.dwDebugEventCode);
514 DEBUG_EVENTS (("ContinueDebugEvent (cpid=%d, ctid=%d, DBG_CONTINUE);\n",
515 current_process_id, current_thread_id));
516 CHECK (ContinueDebugEvent (current_process_id,
523 /* Attach to process PID, then initialize for debugging it. */
526 child_attach (args, from_tty)
533 error_no_arg ("process-id to attach");
535 current_process_id = strtoul (args, 0, 0);
537 ok = DebugActiveProcess (current_process_id);
540 error ("Can't attach to process.");
548 char *exec_file = (char *) get_exec_file (0);
551 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
552 target_pid_to_str (current_process_id));
554 printf_unfiltered ("Attaching to %s\n",
555 target_pid_to_str (current_process_id));
557 gdb_flush (gdb_stdout);
560 inferior_pid = current_process_id;
561 push_target (&child_ops);
566 child_detach (args, from_tty)
572 char *exec_file = get_exec_file (0);
575 printf_unfiltered ("Detaching from program: %s %s\n", exec_file,
576 target_pid_to_str (inferior_pid));
577 gdb_flush (gdb_stdout);
580 unpush_target (&child_ops);
584 /* Print status information about what we're accessing. */
587 child_files_info (ignore)
588 struct target_ops *ignore;
590 printf_unfiltered ("\tUsing the running image of %s %s.\n",
591 attach_flag ? "attached" : "child", target_pid_to_str (inferior_pid));
596 child_open (arg, from_tty)
600 error ("Use the \"run\" command to start a Unix child process.");
603 /* Start an inferior win32 child process and sets inferior_pid to its pid.
604 EXEC_FILE is the file to run.
605 ALLARGS is a string containing the arguments to the program.
606 ENV is the environment vector to pass. Errors reported with error(). */
609 child_create_inferior (exec_file, allargs, env)
614 char real_path[MAXPATHLEN];
621 PROCESS_INFORMATION pi;
622 struct target_waitstatus dummy;
629 error ("No executable specified, use `target exec'.\n");
632 memset (&si, 0, sizeof (si));
635 cygwin32_conv_to_win32_path (exec_file, real_path);
637 flags = DEBUG_ONLY_THIS_PROCESS;
640 flags |= CREATE_NEW_PROCESS_GROUP;
643 flags |= CREATE_NEW_CONSOLE;
645 args = alloca (strlen (real_path) + strlen (allargs) + 2);
647 strcpy (args, real_path);
650 strcat (args, allargs);
652 /* Prepare the environment vars for CreateProcess. */
654 /* This code use to assume all env vars were file names and would
655 translate them all to win32 style. That obviously doesn't work in the
656 general case. The current rule is that we only translate PATH.
657 We need to handle PATH because we're about to call CreateProcess and
658 it uses PATH to find DLL's. Fortunately PATH has a well-defined value
659 in both posix and win32 environments. cygwin.dll will change it back
660 to posix style if necessary. */
662 static const char *conv_path_names[] =
668 /* CreateProcess takes the environment list as a null terminated set of
669 strings (i.e. two nulls terminate the list). */
671 /* Get total size for env strings. */
672 for (envlen = 0, i = 0; env[i] && *env[i]; i++)
676 for (j = 0; conv_path_names[j]; j++)
678 len = strlen (conv_path_names[j]);
679 if (strncmp (conv_path_names[j], env[i], len) == 0)
681 if (cygwin32_posix_path_list_p (env[i] + len))
683 + cygwin32_posix_to_win32_path_list_buf_size (env[i] + len);
685 envlen += strlen (env[i]) + 1;
689 if (conv_path_names[j] == NULL)
690 envlen += strlen (env[i]) + 1;
693 winenv = alloca (envlen + 1);
695 /* Copy env strings into new buffer. */
696 for (temp = winenv, i = 0; env[i] && *env[i]; i++)
700 for (j = 0; conv_path_names[j]; j++)
702 len = strlen (conv_path_names[j]);
703 if (strncmp (conv_path_names[j], env[i], len) == 0)
705 if (cygwin32_posix_path_list_p (env[i] + len))
707 memcpy (temp, env[i], len);
708 cygwin32_posix_to_win32_path_list (env[i] + len, temp + len);
711 strcpy (temp, env[i]);
715 if (conv_path_names[j] == NULL)
716 strcpy (temp, env[i]);
718 temp += strlen (temp) + 1;
721 /* Final nil string to terminate new env. */
725 ret = CreateProcess (0,
726 args, /* command line */
729 TRUE, /* inherit handles */
730 flags, /* start flags */
732 NULL, /* current directory */
736 error ("Error creating process %s, (error %d)\n", exec_file, GetLastError());
741 inferior_pid = pi.dwProcessId;
742 current_process = pi.hProcess;
743 current_thread = pi.hThread;
744 current_process_id = pi.dwProcessId;
745 current_thread_id = pi.dwThreadId;
746 push_target (&child_ops);
748 init_wait_for_inferior ();
749 clear_proceed_status ();
750 target_terminal_init ();
751 target_terminal_inferior ();
753 /* Ignore the first trap */
754 child_wait (inferior_pid, &dummy);
756 proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
760 child_mourn_inferior ()
762 unpush_target (&child_ops);
763 generic_mourn_inferior ();
767 /* Send a SIGINT to the process group. This acts just like the user typed a
768 ^C on the controlling terminal. */
773 DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
774 CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0));
775 registers_changed(); /* refresh register state */
779 child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
780 int write, struct target_ops *target)
785 DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08x\n",
787 WriteProcessMemory (current_process, memaddr, our, len, &done);
788 FlushInstructionCache (current_process, memaddr, len);
792 DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08x\n",
794 ReadProcessMemory (current_process, memaddr, our, len, &done);
800 child_kill_inferior (void)
802 CHECK (TerminateProcess (current_process, 0));
803 CHECK (CloseHandle (current_process));
804 CHECK (CloseHandle (current_thread));
805 target_mourn_inferior(); /* or just child_mourn_inferior? */
809 child_resume (int pid, int step, enum target_signal signal)
811 DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, signal=%d);\n",
817 warning ("Single stepping not done.\n");
820 /* Single step by setting t bit */
821 child_fetch_inferior_registers (PS_REGNUM);
822 context.EFlags |= FLAG_TRACE_BIT;
826 if (context.ContextFlags)
828 CHECK (SetThreadContext (current_thread, &context));
829 context.ContextFlags = 0;
834 fprintf_unfiltered (gdb_stderr, "Can't send signals to the child.\n");
837 DEBUG_EVENTS (("gdb: ContinueDebugEvent (cpid=%d, ctid=%d, DBG_CONTINUE);\n",
838 current_process_id, current_thread_id));
839 CHECK (ContinueDebugEvent (current_process_id,
845 child_prepare_to_store ()
847 /* Do nothing, since we can store individual regs */
859 DEBUG_EVENTS (("gdb: child_close, inferior_pid=%d\n", inferior_pid));
862 struct target_ops child_ops =
864 "child", /* to_shortname */
865 "Win32 child process", /* to_longname */
866 "Win32 child process (started by the \"run\" command).", /* to_doc */
867 child_open, /* to_open */
868 child_close, /* to_close */
869 child_attach, /* to_attach */
870 child_detach, /* to_detach */
871 child_resume, /* to_resume */
872 child_wait, /* to_wait */
873 child_fetch_inferior_registers,/* to_fetch_registers */
874 child_store_inferior_registers,/* to_store_registers */
875 child_prepare_to_store, /* to_child_prepare_to_store */
876 child_xfer_memory, /* to_xfer_memory */
877 child_files_info, /* to_files_info */
878 memory_insert_breakpoint, /* to_insert_breakpoint */
879 memory_remove_breakpoint, /* to_remove_breakpoint */
880 terminal_init_inferior, /* to_terminal_init */
881 terminal_inferior, /* to_terminal_inferior */
882 terminal_ours_for_output, /* to_terminal_ours_for_output */
883 terminal_ours, /* to_terminal_ours */
884 child_terminal_info, /* to_terminal_info */
885 child_kill_inferior, /* to_kill */
887 0, /* to_lookup_symbol */
888 child_create_inferior, /* to_create_inferior */
889 child_mourn_inferior, /* to_mourn_inferior */
890 child_can_run, /* to_can_run */
891 0, /* to_notice_signals */
892 0, /* to_thread_alive */
893 child_stop, /* to_stop */
894 process_stratum, /* to_stratum */
896 1, /* to_has_all_memory */
897 1, /* to_has_memory */
898 1, /* to_has_stack */
899 1, /* to_has_registers */
900 1, /* to_has_execution */
902 0, /* to_sections_end */
903 OPS_MAGIC /* to_magic */
907 _initialize_inftarg ()
909 struct cmd_list_element *c;
912 (add_set_cmd ("new-console", class_support, var_boolean,
913 (char *) &new_console,
914 "Set creation of new console when creating child process.",
919 (add_set_cmd ("new-group", class_support, var_boolean,
921 "Set creation of new group when creating child process.",
926 (add_set_cmd ("debugexec", class_support, var_boolean,
927 (char *) &debug_exec,
928 "Set whether to display execution in child process.",
933 (add_set_cmd ("debugevents", class_support, var_boolean,
934 (char *) &debug_events,
935 "Set whether to display kernel events in child process.",
940 (add_set_cmd ("debugmemory", class_support, var_boolean,
941 (char *) &debug_memory,
942 "Set whether to display memory accesses in child process.",
947 (add_set_cmd ("debugexceptions", class_support, var_boolean,
948 (char *) &debug_exceptions,
949 "Set whether to display kernel exceptions in child process.",
953 add_target (&child_ops);