]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/win32-nat.c
* as.h (SEG_NORMAL, SEG_LIST): Bump segment limit from 10 to 40.
[thirdparty/binutils-gdb.git] / gdb / win32-nat.c
CommitLineData
24e60978 1/* Target-vector operations for controlling win32 child processes, for GDB.
454ffae5 2 Copyright 1995, 1996
24e60978
SC
3 Free Software Foundation, Inc.
4
5 Contributed by Cygnus Support.
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 eve nthe 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21
22/* by Steve Chamberlain, sac@cygnus.com */
23
24#include "defs.h"
25#include "frame.h" /* required by inferior.h */
26#include "inferior.h"
27#include "target.h"
28#include "wait.h"
29#include "gdbcore.h"
30#include "command.h"
31#include <signal.h>
32#include <sys/types.h>
33#include <fcntl.h>
34#include <windows.h>
35#include "buildsym.h"
36#include "gdb_string.h"
37#include "thread.h"
38#include "gdbcmd.h"
1750a5ef 39#include <sys/param.h>
24e60978
SC
40#define CHECK(x) check (x, __FILE__,__LINE__)
41#define DEBUG(x) if (remote_debug) printf x
42
43
44/* Forward declaration */
45extern struct target_ops child_ops;
46
47/* The most recently read context. Inspect ContextFlags to see what
48 bits are valid. */
49
50static CONTEXT context;
51
52/* The process and thread handles for the above context. */
53
54static HANDLE current_process;
55static HANDLE current_thread;
56static int current_process_id;
57static int current_thread_id;
58
59/* Counts of things. */
60static int exception_count = 0;
61static int event_count = 0;
62
63/* User options. */
64static int new_console = 0;
65static int new_group = 0;
66
67/* This vector maps GDB's idea of a register's number into an address
68 in the win32 exception context vector.
69
70 It also contains the bit mask needed to load the register in question.
71
72 One day we could read a reg, we could inspect the context we
73 already have loaded, if it doesn't have the bit set that we need,
74 we read that set of registers in using GetThreadContext. If the
75 context already contains what we need, we just unpack it. Then to
76 write a register, first we have to ensure that the context contains
77 the other regs of the group, and then we copy the info in and set
78 out bit. */
79
80struct regmappings
81 {
82 char *incontext;
83 int mask;
84 };
85
454ffae5
SC
86
87static const struct regmappings mappings[] =
24e60978 88{
454ffae5
SC
89#ifdef __PPC__
90 {(char *) &context.Gpr0, CONTEXT_INTEGER},
91 {(char *) &context.Gpr1, CONTEXT_INTEGER},
92 {(char *) &context.Gpr2, CONTEXT_INTEGER},
93 {(char *) &context.Gpr3, CONTEXT_INTEGER},
94 {(char *) &context.Gpr4, CONTEXT_INTEGER},
95 {(char *) &context.Gpr5, CONTEXT_INTEGER},
96 {(char *) &context.Gpr6, CONTEXT_INTEGER},
97 {(char *) &context.Gpr7, CONTEXT_INTEGER},
98
99 {(char *) &context.Gpr8, CONTEXT_INTEGER},
100 {(char *) &context.Gpr9, CONTEXT_INTEGER},
101 {(char *) &context.Gpr10, CONTEXT_INTEGER},
102 {(char *) &context.Gpr11, CONTEXT_INTEGER},
103 {(char *) &context.Gpr12, CONTEXT_INTEGER},
104 {(char *) &context.Gpr13, CONTEXT_INTEGER},
105 {(char *) &context.Gpr14, CONTEXT_INTEGER},
106 {(char *) &context.Gpr15, CONTEXT_INTEGER},
107
108 {(char *) &context.Gpr16, CONTEXT_INTEGER},
109 {(char *) &context.Gpr17, CONTEXT_INTEGER},
110 {(char *) &context.Gpr18, CONTEXT_INTEGER},
111 {(char *) &context.Gpr19, CONTEXT_INTEGER},
112 {(char *) &context.Gpr20, CONTEXT_INTEGER},
113 {(char *) &context.Gpr21, CONTEXT_INTEGER},
114 {(char *) &context.Gpr22, CONTEXT_INTEGER},
115 {(char *) &context.Gpr23, CONTEXT_INTEGER},
116
117 {(char *) &context.Gpr24, CONTEXT_INTEGER},
118 {(char *) &context.Gpr25, CONTEXT_INTEGER},
119 {(char *) &context.Gpr26, CONTEXT_INTEGER},
120 {(char *) &context.Gpr27, CONTEXT_INTEGER},
121 {(char *) &context.Gpr28, CONTEXT_INTEGER},
122 {(char *) &context.Gpr29, CONTEXT_INTEGER},
123 {(char *) &context.Gpr30, CONTEXT_INTEGER},
124 {(char *) &context.Gpr31, CONTEXT_INTEGER},
125
126 {(char *) &context.Fpr0, CONTEXT_FLOATING_POINT},
127 {(char *) &context.Fpr1, CONTEXT_FLOATING_POINT},
128 {(char *) &context.Fpr2, CONTEXT_FLOATING_POINT},
129 {(char *) &context.Fpr3, CONTEXT_FLOATING_POINT},
130 {(char *) &context.Fpr4, CONTEXT_FLOATING_POINT},
131 {(char *) &context.Fpr5, CONTEXT_FLOATING_POINT},
132 {(char *) &context.Fpr6, CONTEXT_FLOATING_POINT},
133 {(char *) &context.Fpr7, CONTEXT_FLOATING_POINT},
134
135 {(char *) &context.Fpr8, CONTEXT_FLOATING_POINT},
136 {(char *) &context.Fpr9, CONTEXT_FLOATING_POINT},
137 {(char *) &context.Fpr10, CONTEXT_FLOATING_POINT},
138 {(char *) &context.Fpr11, CONTEXT_FLOATING_POINT},
139 {(char *) &context.Fpr12, CONTEXT_FLOATING_POINT},
140 {(char *) &context.Fpr13, CONTEXT_FLOATING_POINT},
141 {(char *) &context.Fpr14, CONTEXT_FLOATING_POINT},
142 {(char *) &context.Fpr15, CONTEXT_FLOATING_POINT},
143
144 {(char *) &context.Fpr16, CONTEXT_FLOATING_POINT},
145 {(char *) &context.Fpr17, CONTEXT_FLOATING_POINT},
146 {(char *) &context.Fpr18, CONTEXT_FLOATING_POINT},
147 {(char *) &context.Fpr19, CONTEXT_FLOATING_POINT},
148 {(char *) &context.Fpr20, CONTEXT_FLOATING_POINT},
149 {(char *) &context.Fpr21, CONTEXT_FLOATING_POINT},
150 {(char *) &context.Fpr22, CONTEXT_FLOATING_POINT},
151 {(char *) &context.Fpr23, CONTEXT_FLOATING_POINT},
152
153 {(char *) &context.Fpr24, CONTEXT_FLOATING_POINT},
154 {(char *) &context.Fpr25, CONTEXT_FLOATING_POINT},
155 {(char *) &context.Fpr26, CONTEXT_FLOATING_POINT},
156 {(char *) &context.Fpr27, CONTEXT_FLOATING_POINT},
157 {(char *) &context.Fpr28, CONTEXT_FLOATING_POINT},
158 {(char *) &context.Fpr29, CONTEXT_FLOATING_POINT},
159 {(char *) &context.Fpr30, CONTEXT_FLOATING_POINT},
160 {(char *) &context.Fpr31, CONTEXT_FLOATING_POINT},
161
162
163 {(char *) &context.Iar, CONTEXT_CONTROL},
164 {(char *) &context.Msr, CONTEXT_CONTROL},
165 {(char *) &context.Cr, CONTEXT_INTEGER},
166 {(char *) &context.Lr, CONTEXT_CONTROL},
167 {(char *) &context.Ctr, CONTEXT_CONTROL},
168
169 {(char *) &context.Xer, CONTEXT_INTEGER},
170 {0,0}, /* MQ, but there isn't one */
171#else
24e60978
SC
172 {(char *) &context.Eax, CONTEXT_INTEGER},
173 {(char *) &context.Ecx, CONTEXT_INTEGER},
174 {(char *) &context.Edx, CONTEXT_INTEGER},
175 {(char *) &context.Ebx, CONTEXT_INTEGER},
176 {(char *) &context.Esp, CONTEXT_CONTROL},
177 {(char *) &context.Ebp, CONTEXT_CONTROL},
178 {(char *) &context.Esi, CONTEXT_INTEGER},
179 {(char *) &context.Edi, CONTEXT_INTEGER},
180 {(char *) &context.Eip, CONTEXT_CONTROL},
181 {(char *) &context.EFlags, CONTEXT_CONTROL},
182 {(char *) &context.SegCs, CONTEXT_SEGMENTS},
183 {(char *) &context.SegSs, CONTEXT_SEGMENTS},
184 {(char *) &context.SegDs, CONTEXT_SEGMENTS},
185 {(char *) &context.SegEs, CONTEXT_SEGMENTS},
186 {(char *) &context.SegFs, CONTEXT_SEGMENTS},
187 {(char *) &context.SegGs, CONTEXT_SEGMENTS},
188 {&context.FloatSave.RegisterArea[0 * 10], CONTEXT_FLOATING_POINT},
189 {&context.FloatSave.RegisterArea[1 * 10], CONTEXT_FLOATING_POINT},
190 {&context.FloatSave.RegisterArea[2 * 10], CONTEXT_FLOATING_POINT},
191 {&context.FloatSave.RegisterArea[3 * 10], CONTEXT_FLOATING_POINT},
192 {&context.FloatSave.RegisterArea[4 * 10], CONTEXT_FLOATING_POINT},
193 {&context.FloatSave.RegisterArea[5 * 10], CONTEXT_FLOATING_POINT},
194 {&context.FloatSave.RegisterArea[6 * 10], CONTEXT_FLOATING_POINT},
195 {&context.FloatSave.RegisterArea[7 * 10], CONTEXT_FLOATING_POINT},
454ffae5 196#endif
24e60978
SC
197};
198
199
200/* This vector maps the target's idea of an exception (extracted
201 from the DEBUG_EVENT structure) to GDB's idea. */
202
203struct xlate_exception
204 {
205 int them;
206 enum target_signal us;
207 };
208
209
210static const struct xlate_exception
211 xlate[] =
212{
213 {EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV},
9cbf6c0e 214 {STATUS_STACK_OVERFLOW, TARGET_SIGNAL_SEGV},
24e60978
SC
215 {EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP},
216 {DBG_CONTROL_C, TARGET_SIGNAL_INT},
217 {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP},
218 {-1, -1}};
219
220
221static void
222check (BOOL ok, const char *file, int line)
223{
224 if (!ok)
225 printf_filtered ("error return %s:%d was %d\n", file, line, GetLastError ());
226}
227
228static void
229child_fetch_inferior_registers (int r)
230{
231 if (r < 0)
232 {
233 for (r = 0; r < NUM_REGS; r++)
234 child_fetch_inferior_registers (r);
235 }
236 else
237 {
238 supply_register (r, mappings[r].incontext);
239 }
240}
241
242static void
243child_store_inferior_registers (int r)
244{
245 if (r < 0)
246 {
247 for (r = 0; r < NUM_REGS; r++)
248 child_store_inferior_registers (r);
249 }
250 else
251 {
252 read_register_gen (r, mappings[r].incontext);
253 }
254}
255
256
257/* Wait for child to do something. Return pid of child, or -1 in case
258 of error; store status through argument pointer OURSTATUS. */
259
260
1750a5ef
SC
261static int
262handle_load_dll (char *eventp)
24e60978 263{
1750a5ef 264 DEBUG_EVENT * event = (DEBUG_EVENT *)eventp;
24e60978
SC
265 DWORD dll_name_ptr;
266 DWORD done;
267
268 ReadProcessMemory (current_process,
269 (DWORD) event->u.LoadDll.lpImageName,
270 (char *) &dll_name_ptr,
271 sizeof (dll_name_ptr), &done);
272
273 /* See if we could read the address of a string, and that the
274 address isn't null. */
275
276 if (done == sizeof (dll_name_ptr) && dll_name_ptr)
277 {
278 char *dll_name;
279 int size = event->u.LoadDll.fUnicode ? sizeof (WCHAR) : sizeof (char);
280 int len = 0;
281 char b[2];
282 do
283 {
284 ReadProcessMemory (current_process,
285 dll_name_ptr + len * size,
286 &b,
287 size,
288 &done);
289 len++;
290 }
291 while ((b[0] != 0 || b[size - 1] != 0) && done == size);
292
293
294 dll_name = alloca (len);
295
296 if (event->u.LoadDll.fUnicode)
297 {
298 WCHAR *unicode_dll_name = (WCHAR *) alloca (len * sizeof (WCHAR));
299 ReadProcessMemory (current_process,
300 dll_name_ptr,
301 unicode_dll_name,
302 len * sizeof (WCHAR),
303 &done);
304
305 WideCharToMultiByte (CP_ACP, 0,
306 unicode_dll_name, len,
307 dll_name, len, 0, 0);
308 }
309 else
310 {
311 ReadProcessMemory (current_process,
312 dll_name_ptr,
313 dll_name,
314 len,
315 &done);
316 }
317
318 /* FIXME!! It would be nice to define one symbol which pointed to the
319 front of the dll if we can't find any symbols. */
320
321 context.ContextFlags = CONTEXT_FULL;
322 GetThreadContext (current_thread, &context);
323
1750a5ef
SC
324 /* The symbols in a dll are offset by 0x1000, which is the
325 the offset from 0 of the first byte in an image - because
326 of the file header and the section alignment.
327
328 FIXME: Is this the real reason that we need the 0x1000 ? */
329
330
331 symbol_file_add (dll_name, 0,
332 (int) event->u.LoadDll.lpBaseOfDll + 0x1000, 0, 0, 0);
24e60978
SC
333
334 /* We strip off the path of the dll for tidiness. */
335 if (strrchr (dll_name, '\\'))
336 dll_name = strrchr (dll_name, '\\') + 1;
1750a5ef 337
24e60978
SC
338 printf_unfiltered ("%x:%s\n", event->u.LoadDll.lpBaseOfDll, dll_name);
339 }
1750a5ef 340 return 1;
24e60978
SC
341}
342
343
344static void
345handle_exception (DEBUG_EVENT * event, struct target_waitstatus *ourstatus)
346{
347 int i;
348 int done = 0;
349 ourstatus->kind = TARGET_WAITKIND_STOPPED;
350
351 for (i = 0; !done && xlate[i].us > 0; i++)
352 {
353 if (xlate[i].them == event->u.Exception.ExceptionRecord.ExceptionCode)
354 {
355 ourstatus->value.sig = xlate[i].us;
356 done = 1;
357 break;
358 }
359 }
360
361 if (!done)
362 {
363 printf_unfiltered ("Want to know about exception code %08x\n",
364 event->u.Exception.ExceptionRecord.ExceptionCode);
365 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
366 }
367 context.ContextFlags = CONTEXT_FULL;
368 GetThreadContext (current_thread, &context);
369 exception_count++;
370}
371
372static int
373child_wait (int pid, struct target_waitstatus *ourstatus)
374{
375 /* We loop when we get a non-standard exception rather than return
376 with a SPURIOUS because resume can try and step or modify things,
377 which needs a current_thread. But some of these exceptions mark
378 the birth or death of threads, which mean that the current thread
379 isn't necessarily what you think it is. */
380
381 while (1)
382 {
383 DEBUG_EVENT event;
384 BOOL t = WaitForDebugEvent (&event, INFINITE);
385
386 DEBUG (("%d = WaitForDebugEvent() code=%d pid=%d tid=%d)\n",
387 t,
388 event.dwDebugEventCode,
389 event.dwProcessId,
390 event.dwThreadId));
391
392 event_count++;
393
394 current_thread_id = event.dwThreadId;
395 current_process_id = event.dwProcessId;
396
397 switch (event.dwDebugEventCode)
398 {
399 case CREATE_THREAD_DEBUG_EVENT:
400 case EXIT_THREAD_DEBUG_EVENT:
401 case CREATE_PROCESS_DEBUG_EVENT:
402 break;
403
404 case EXIT_PROCESS_DEBUG_EVENT:
405 ourstatus->kind = TARGET_WAITKIND_EXITED;
406 ourstatus->value.integer = event.u.ExitProcess.dwExitCode;
407 CloseHandle (current_process);
408 CloseHandle (current_thread);
409 return current_process_id;
410 break;
411
412 case LOAD_DLL_DEBUG_EVENT:
1750a5ef
SC
413 catch_errors (handle_load_dll,
414 (char*) &event,
415 "\n[failed reading symbols from DLL]\n",
416 RETURN_MASK_ALL);
417 registers_changed(); /* mark all regs invalid */
24e60978
SC
418 break;
419 case EXCEPTION_DEBUG_EVENT:
420 handle_exception (&event, ourstatus);
421 return current_process_id;
422 default:
423 printf_unfiltered ("waitfor it %d %d %d %d\n", t,
424 event.dwDebugEventCode,
425 event.dwProcessId,
426 event.dwThreadId);
427 break;
428 }
429 CHECK (ContinueDebugEvent (current_process_id,
430 current_thread_id,
431 DBG_CONTINUE));
432 }
433}
434
435
436
437
438/* Attach to process PID, then initialize for debugging it. */
439
440static void
441child_attach (args, from_tty)
442 char *args;
443 int from_tty;
444{
445 BOOL ok;
446
447 if (!args)
448 error_no_arg ("process-id to attach");
449
450 current_process_id = strtoul (args, 0, 0);
451
452 ok = DebugActiveProcess (current_process_id);
453
454 if (!ok)
455 error ("Can't attach to process.");
456
457
458 exception_count = 0;
459 event_count = 0;
460
461 if (from_tty)
462 {
463 char *exec_file = (char *) get_exec_file (0);
464
465 if (exec_file)
466 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
467 target_pid_to_str (current_process_id));
468 else
469 printf_unfiltered ("Attaching to %s\n",
470 target_pid_to_str (current_process_id));
471
472 gdb_flush (gdb_stdout);
473 }
474
475 inferior_pid = current_process_id;
476 push_target (&child_ops);
477}
478
479
480static void
481child_detach (args, from_tty)
482 char *args;
483 int from_tty;
484{
485 if (from_tty)
486 {
487 char *exec_file = get_exec_file (0);
488 if (exec_file == 0)
489 exec_file = "";
490 printf_unfiltered ("Detaching from program: %s %s\n", exec_file,
491 target_pid_to_str (inferior_pid));
492 gdb_flush (gdb_stdout);
493 }
494 inferior_pid = 0;
495 unpush_target (&child_ops);
496}
497
498
499/* Print status information about what we're accessing. */
500
501static void
502child_files_info (ignore)
503 struct target_ops *ignore;
504{
505 printf_unfiltered ("\tUsing the running image of %s %s.\n",
506 attach_flag ? "attached" : "child", target_pid_to_str (inferior_pid));
507}
508
509/* ARGSUSED */
510static void
511child_open (arg, from_tty)
512 char *arg;
513 int from_tty;
514{
515 error ("Use the \"run\" command to start a Unix child process.");
516}
517
24e60978 518
eb708f2e 519/* Start an inferior win32 child process and sets inferior_pid to its pid.
24e60978
SC
520 EXEC_FILE is the file to run.
521 ALLARGS is a string containing the arguments to the program.
522 ENV is the environment vector to pass. Errors reported with error(). */
523
524
525static void
526child_create_inferior (exec_file, allargs, env)
527 char *exec_file;
528 char *allargs;
529 char **env;
530{
1750a5ef
SC
531 char real_path[MAXPATHLEN];
532 char *winenv;
533 char *temp;
534 int envlen;
535 int i;
536
24e60978
SC
537 STARTUPINFO si;
538 PROCESS_INFORMATION pi;
539 struct target_waitstatus dummy;
540 BOOL ret;
541 DWORD flags;
eb708f2e 542 char *args;
24e60978
SC
543
544 if (!exec_file)
545 {
546 error ("No executable specified, use `target exec'.\n");
547 }
548
549 memset (&si, 0, sizeof (si));
550 si.cb = sizeof (si);
551
1750a5ef 552 unix_path_to_dos_path (exec_file, real_path);
24e60978
SC
553
554 flags = DEBUG_ONLY_THIS_PROCESS | DEBUG_PROCESS;
555
556 if (new_group)
557 flags |= CREATE_NEW_PROCESS_GROUP;
558
559 if (new_console)
560 flags |= CREATE_NEW_CONSOLE;
561
3d78f532
SC
562 args = alloca (strlen (real_path) + strlen (allargs) + 2);
563
564 strcpy (args, real_path);
eb708f2e 565
eb708f2e
SC
566 strcat (args, " ");
567 strcat (args, allargs);
568
1750a5ef
SC
569
570 /* get total size for env strings */
571 for (envlen = 0, i = 0; env[i] && *env[i]; i++)
572 envlen += strlen(env[i]) + 1;
573
574 winenv = alloca(envlen + 1); /* allocate new buffer */
575
576 /* copy env strings into new buffer */
3d78f532 577 for (temp = winenv, i = 0; env[i] && *env[i]; i++)
1750a5ef
SC
578 {
579 strcpy(temp, env[i]);
580 temp += strlen(temp) + 1;
581 }
582 *temp = 0; /* final nil string to terminate new env */
583
1750a5ef 584 ret = CreateProcess (0,
3d78f532 585 args, /* command line */
24e60978
SC
586 NULL, /* Security */
587 NULL, /* thread */
588 TRUE, /* inherit handles */
589 flags, /* start flags */
1750a5ef 590 winenv,
24e60978
SC
591 NULL, /* current directory */
592 &si,
593 &pi);
594 if (!ret)
686941a9 595 error ("Error creating process %s, (error %d)\n", exec_file, GetLastError());
24e60978
SC
596
597 exception_count = 0;
598 event_count = 0;
599
600 inferior_pid = pi.dwProcessId;
601 current_process = pi.hProcess;
602 current_thread = pi.hThread;
603 current_process_id = pi.dwProcessId;
604 current_thread_id = pi.dwThreadId;
605 push_target (&child_ops);
606 init_thread_list ();
607 init_wait_for_inferior ();
608 clear_proceed_status ();
609 target_terminal_init ();
610 target_terminal_inferior ();
611
612 /* Ignore the first trap */
613 child_wait (inferior_pid, &dummy);
614
615 proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
616}
617
618static void
619child_mourn_inferior ()
620{
621 unpush_target (&child_ops);
622 generic_mourn_inferior ();
623}
624
625
626/* Send a SIGINT to the process group. This acts just like the user typed a
627 ^C on the controlling terminal. */
628
629void
630child_stop ()
631{
632 CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0));
633}
634
635int
eb708f2e
SC
636child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
637 int write, struct target_ops *target)
24e60978
SC
638{
639 DWORD done;
640 if (write)
641 {
642 WriteProcessMemory (current_process, memaddr, our, len, &done);
643 FlushInstructionCache (current_process, memaddr, len);
644 }
645 else
646 {
647 ReadProcessMemory (current_process, memaddr, our, len, &done);
648 }
649 return done;
650}
651
652void
653child_kill_inferior (void)
654{
655 CHECK (TerminateProcess (current_process, 0));
656 CHECK (CloseHandle (current_process));
657 CHECK (CloseHandle (current_thread));
658}
659
660void
661child_resume (int pid, int step, enum target_signal signal)
662{
663 DEBUG (("child_resume (%d, %d, %d);\n", pid, step, signal));
664
665 if (step)
666 {
454ffae5
SC
667#ifdef __PPC__
668 warning ("Single stepping not done.\n");
669#endif
670#ifdef __I386__
24e60978
SC
671 /* Single step by setting t bit */
672 child_fetch_inferior_registers (PS_REGNUM);
673 context.EFlags |= FLAG_TRACE_BIT;
454ffae5 674#endif
24e60978
SC
675 }
676
677 if (context.ContextFlags)
678 {
679 CHECK (SetThreadContext (current_thread, &context));
680 context.ContextFlags = 0;
681 }
682
683 if (signal)
684 {
685 fprintf_unfiltered (gdb_stderr, "Can't send signals to the child.\n");
686 }
687
688 CHECK (ContinueDebugEvent (current_process_id,
689 current_thread_id,
690 DBG_CONTINUE));
691}
692
693static void
694child_prepare_to_store ()
695{
696 /* Do nothing, since we can store individual regs */
697}
698
699static int
700child_can_run ()
701{
702 return 1;
703}
704
705static void
706child_close ()
707{
708
709}
710struct target_ops child_ops =
711{
712 "child", /* to_shortname */
713 "Win32 child process", /* to_longname */
714 "Win32 child process (started by the \"run\" command).", /* to_doc */
715 child_open, /* to_open */
716 child_close, /* to_close */
717 child_attach, /* to_attach */
718 child_detach, /* to_detach */
719 child_resume, /* to_resume */
720 child_wait, /* to_wait */
721 child_fetch_inferior_registers,/* to_fetch_registers */
722 child_store_inferior_registers,/* to_store_registers */
723 child_prepare_to_store, /* to_child_prepare_to_store */
724 child_xfer_memory, /* to_xfer_memory */
725 child_files_info, /* to_files_info */
726 memory_insert_breakpoint, /* to_insert_breakpoint */
727 memory_remove_breakpoint, /* to_remove_breakpoint */
728 terminal_init_inferior, /* to_terminal_init */
729 terminal_inferior, /* to_terminal_inferior */
730 terminal_ours_for_output, /* to_terminal_ours_for_output */
731 terminal_ours, /* to_terminal_ours */
732 child_terminal_info, /* to_terminal_info */
733 child_kill_inferior, /* to_kill */
734 0, /* to_load */
735 0, /* to_lookup_symbol */
736 child_create_inferior, /* to_create_inferior */
737 child_mourn_inferior, /* to_mourn_inferior */
738 child_can_run, /* to_can_run */
739 0, /* to_notice_signals */
740 0, /* to_thread_alive */
741 child_stop, /* to_stop */
742 process_stratum, /* to_stratum */
743 0, /* to_next */
744 1, /* to_has_all_memory */
745 1, /* to_has_memory */
746 1, /* to_has_stack */
747 1, /* to_has_registers */
748 1, /* to_has_execution */
749 0, /* to_sections */
750 0, /* to_sections_end */
751 OPS_MAGIC /* to_magic */
752};
753
754void
755_initialize_inftarg ()
756{
757 add_show_from_set
758 (add_set_cmd ("new-console", class_support, var_boolean,
759 (char *) &new_console,
760 "Set creation of new console when creating child process.",
761 &setlist),
762 &showlist);
763
764 add_show_from_set
765 (add_set_cmd ("new-group", class_support, var_boolean,
766 (char *) &new_group,
767 "Set creation of new group when creating child process.",
768 &setlist),
769 &showlist);
770
771 add_target (&child_ops);
772}