1 /* Target-vector operations for controlling win32 child processes, for GDB.
3 Free Software Foundation, Inc.
5 Contributed by Cygnus Support.
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 eve nthe 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 /* by Steve Chamberlain, sac@cygnus.com */
25 #include "frame.h" /* required by inferior.h */
32 #include <sys/types.h>
36 #include "gdb_string.h"
40 #define CHECK(x) check (x, __FILE__,__LINE__)
41 #define DEBUG(x) if (remote_debug) printf x
44 /* Forward declaration */
45 extern struct target_ops child_ops
;
47 /* The most recently read context. Inspect ContextFlags to see what
50 static CONTEXT context
;
52 /* The process and thread handles for the above context. */
54 static HANDLE current_process
;
55 static HANDLE current_thread
;
56 static int current_process_id
;
57 static int current_thread_id
;
59 /* Counts of things. */
60 static int exception_count
= 0;
61 static int event_count
= 0;
64 static int new_console
= 0;
65 static int new_group
= 0;
67 /* This vector maps GDB's idea of a register's number into an address
68 in the win32 exception context vector.
70 It also contains the bit mask needed to load the register in question.
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
86 static const struct regmappings
89 {(char *) &context
.Eax
, CONTEXT_INTEGER
},
90 {(char *) &context
.Ecx
, CONTEXT_INTEGER
},
91 {(char *) &context
.Edx
, CONTEXT_INTEGER
},
92 {(char *) &context
.Ebx
, CONTEXT_INTEGER
},
93 {(char *) &context
.Esp
, CONTEXT_CONTROL
},
94 {(char *) &context
.Ebp
, CONTEXT_CONTROL
},
95 {(char *) &context
.Esi
, CONTEXT_INTEGER
},
96 {(char *) &context
.Edi
, CONTEXT_INTEGER
},
97 {(char *) &context
.Eip
, CONTEXT_CONTROL
},
98 {(char *) &context
.EFlags
, CONTEXT_CONTROL
},
99 {(char *) &context
.SegCs
, CONTEXT_SEGMENTS
},
100 {(char *) &context
.SegSs
, CONTEXT_SEGMENTS
},
101 {(char *) &context
.SegDs
, CONTEXT_SEGMENTS
},
102 {(char *) &context
.SegEs
, CONTEXT_SEGMENTS
},
103 {(char *) &context
.SegFs
, CONTEXT_SEGMENTS
},
104 {(char *) &context
.SegGs
, CONTEXT_SEGMENTS
},
105 {&context
.FloatSave
.RegisterArea
[0 * 10], CONTEXT_FLOATING_POINT
},
106 {&context
.FloatSave
.RegisterArea
[1 * 10], CONTEXT_FLOATING_POINT
},
107 {&context
.FloatSave
.RegisterArea
[2 * 10], CONTEXT_FLOATING_POINT
},
108 {&context
.FloatSave
.RegisterArea
[3 * 10], CONTEXT_FLOATING_POINT
},
109 {&context
.FloatSave
.RegisterArea
[4 * 10], CONTEXT_FLOATING_POINT
},
110 {&context
.FloatSave
.RegisterArea
[5 * 10], CONTEXT_FLOATING_POINT
},
111 {&context
.FloatSave
.RegisterArea
[6 * 10], CONTEXT_FLOATING_POINT
},
112 {&context
.FloatSave
.RegisterArea
[7 * 10], CONTEXT_FLOATING_POINT
},
116 /* This vector maps the target's idea of an exception (extracted
117 from the DEBUG_EVENT structure) to GDB's idea. */
119 struct xlate_exception
122 enum target_signal us
;
126 static const struct xlate_exception
129 {EXCEPTION_ACCESS_VIOLATION
, TARGET_SIGNAL_SEGV
},
130 {EXCEPTION_BREAKPOINT
, TARGET_SIGNAL_TRAP
},
131 {DBG_CONTROL_C
, TARGET_SIGNAL_INT
},
132 {EXCEPTION_SINGLE_STEP
, TARGET_SIGNAL_TRAP
},
137 check (BOOL ok
, const char *file
, int line
)
140 printf_filtered ("error return %s:%d was %d\n", file
, line
, GetLastError ());
144 child_fetch_inferior_registers (int r
)
148 for (r
= 0; r
< NUM_REGS
; r
++)
149 child_fetch_inferior_registers (r
);
153 supply_register (r
, mappings
[r
].incontext
);
158 child_store_inferior_registers (int r
)
162 for (r
= 0; r
< NUM_REGS
; r
++)
163 child_store_inferior_registers (r
);
167 read_register_gen (r
, mappings
[r
].incontext
);
172 /* Wait for child to do something. Return pid of child, or -1 in case
173 of error; store status through argument pointer OURSTATUS. */
177 handle_load_dll (DEBUG_EVENT
* event
)
182 ReadProcessMemory (current_process
,
183 (DWORD
) event
->u
.LoadDll
.lpImageName
,
184 (char *) &dll_name_ptr
,
185 sizeof (dll_name_ptr
), &done
);
187 /* See if we could read the address of a string, and that the
188 address isn't null. */
190 if (done
== sizeof (dll_name_ptr
) && dll_name_ptr
)
193 int size
= event
->u
.LoadDll
.fUnicode
? sizeof (WCHAR
) : sizeof (char);
198 ReadProcessMemory (current_process
,
199 dll_name_ptr
+ len
* size
,
205 while ((b
[0] != 0 || b
[size
- 1] != 0) && done
== size
);
208 dll_name
= alloca (len
);
210 if (event
->u
.LoadDll
.fUnicode
)
212 WCHAR
*unicode_dll_name
= (WCHAR
*) alloca (len
* sizeof (WCHAR
));
213 ReadProcessMemory (current_process
,
216 len
* sizeof (WCHAR
),
219 WideCharToMultiByte (CP_ACP
, 0,
220 unicode_dll_name
, len
,
221 dll_name
, len
, 0, 0);
225 ReadProcessMemory (current_process
,
232 /* FIXME!! It would be nice to define one symbol which pointed to the
233 front of the dll if we can't find any symbols. */
235 context
.ContextFlags
= CONTEXT_FULL
;
236 GetThreadContext (current_thread
, &context
);
238 symbol_file_add (dll_name
, 0, (int) event
->u
.LoadDll
.lpBaseOfDll
, 0, 0, 0);
240 /* We strip off the path of the dll for tidiness. */
241 if (strrchr (dll_name
, '\\'))
242 dll_name
= strrchr (dll_name
, '\\') + 1;
243 printf_unfiltered ("%x:%s\n", event
->u
.LoadDll
.lpBaseOfDll
, dll_name
);
249 handle_exception (DEBUG_EVENT
* event
, struct target_waitstatus
*ourstatus
)
253 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
255 for (i
= 0; !done
&& xlate
[i
].us
> 0; i
++)
257 if (xlate
[i
].them
== event
->u
.Exception
.ExceptionRecord
.ExceptionCode
)
259 ourstatus
->value
.sig
= xlate
[i
].us
;
267 printf_unfiltered ("Want to know about exception code %08x\n",
268 event
->u
.Exception
.ExceptionRecord
.ExceptionCode
);
269 ourstatus
->value
.sig
= TARGET_SIGNAL_UNKNOWN
;
271 context
.ContextFlags
= CONTEXT_FULL
;
272 GetThreadContext (current_thread
, &context
);
277 child_wait (int pid
, struct target_waitstatus
*ourstatus
)
279 /* We loop when we get a non-standard exception rather than return
280 with a SPURIOUS because resume can try and step or modify things,
281 which needs a current_thread. But some of these exceptions mark
282 the birth or death of threads, which mean that the current thread
283 isn't necessarily what you think it is. */
288 BOOL t
= WaitForDebugEvent (&event
, INFINITE
);
290 DEBUG (("%d = WaitForDebugEvent() code=%d pid=%d tid=%d)\n",
292 event
.dwDebugEventCode
,
298 current_thread_id
= event
.dwThreadId
;
299 current_process_id
= event
.dwProcessId
;
301 switch (event
.dwDebugEventCode
)
303 case CREATE_THREAD_DEBUG_EVENT
:
304 case EXIT_THREAD_DEBUG_EVENT
:
305 case CREATE_PROCESS_DEBUG_EVENT
:
308 case EXIT_PROCESS_DEBUG_EVENT
:
309 ourstatus
->kind
= TARGET_WAITKIND_EXITED
;
310 ourstatus
->value
.integer
= event
.u
.ExitProcess
.dwExitCode
;
311 CloseHandle (current_process
);
312 CloseHandle (current_thread
);
313 return current_process_id
;
316 case LOAD_DLL_DEBUG_EVENT
:
317 handle_load_dll (&event
);
319 case EXCEPTION_DEBUG_EVENT
:
320 handle_exception (&event
, ourstatus
);
321 return current_process_id
;
323 printf_unfiltered ("waitfor it %d %d %d %d\n", t
,
324 event
.dwDebugEventCode
,
329 CHECK (ContinueDebugEvent (current_process_id
,
338 /* Attach to process PID, then initialize for debugging it. */
341 child_attach (args
, from_tty
)
348 error_no_arg ("process-id to attach");
350 current_process_id
= strtoul (args
, 0, 0);
352 ok
= DebugActiveProcess (current_process_id
);
355 error ("Can't attach to process.");
363 char *exec_file
= (char *) get_exec_file (0);
366 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file
,
367 target_pid_to_str (current_process_id
));
369 printf_unfiltered ("Attaching to %s\n",
370 target_pid_to_str (current_process_id
));
372 gdb_flush (gdb_stdout
);
375 inferior_pid
= current_process_id
;
376 push_target (&child_ops
);
381 child_detach (args
, from_tty
)
387 char *exec_file
= get_exec_file (0);
390 printf_unfiltered ("Detaching from program: %s %s\n", exec_file
,
391 target_pid_to_str (inferior_pid
));
392 gdb_flush (gdb_stdout
);
395 unpush_target (&child_ops
);
399 /* Print status information about what we're accessing. */
402 child_files_info (ignore
)
403 struct target_ops
*ignore
;
405 printf_unfiltered ("\tUsing the running image of %s %s.\n",
406 attach_flag
? "attached" : "child", target_pid_to_str (inferior_pid
));
411 child_open (arg
, from_tty
)
415 error ("Use the \"run\" command to start a Unix child process.");
419 /* Start an inferior win32 child process and sets inferior_pid to its pid.
420 EXEC_FILE is the file to run.
421 ALLARGS is a string containing the arguments to the program.
422 ENV is the environment vector to pass. Errors reported with error(). */
426 child_create_inferior (exec_file
, allargs
, env
)
433 PROCESS_INFORMATION pi
;
434 struct target_waitstatus dummy
;
441 error ("No executable specified, use `target exec'.\n");
444 memset (&si
, 0, sizeof (si
));
447 /* A realpath is always the same size, or a bit shorter than a nice path. */
448 real_path
= alloca (strlen (exec_file
) + 1);
449 path_to_real_path (exec_file
, real_path
);
451 flags
= DEBUG_ONLY_THIS_PROCESS
| DEBUG_PROCESS
;
454 flags
|= CREATE_NEW_PROCESS_GROUP
;
457 flags
|= CREATE_NEW_CONSOLE
;
459 args
= alloca (strlen (exec_file
) + strlen (allargs
) + 2);
461 strcpy (args
, exec_file
);
463 strcat (args
, allargs
);
465 ret
= CreateProcess (real_path
,
469 TRUE
, /* inherit handles */
470 flags
, /* start flags */
472 NULL
, /* current directory */
476 error ("Error creating process %s\n", exec_file
);
481 inferior_pid
= pi
.dwProcessId
;
482 current_process
= pi
.hProcess
;
483 current_thread
= pi
.hThread
;
484 current_process_id
= pi
.dwProcessId
;
485 current_thread_id
= pi
.dwThreadId
;
486 push_target (&child_ops
);
488 init_wait_for_inferior ();
489 clear_proceed_status ();
490 target_terminal_init ();
491 target_terminal_inferior ();
493 /* Ignore the first trap */
494 child_wait (inferior_pid
, &dummy
);
496 proceed ((CORE_ADDR
) - 1, TARGET_SIGNAL_0
, 0);
500 child_mourn_inferior ()
502 unpush_target (&child_ops
);
503 generic_mourn_inferior ();
507 /* Send a SIGINT to the process group. This acts just like the user typed a
508 ^C on the controlling terminal. */
513 CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT
, 0));
517 child_xfer_memory (CORE_ADDR memaddr
, char *our
, int len
,
518 int write
, struct target_ops
*target
)
523 WriteProcessMemory (current_process
, memaddr
, our
, len
, &done
);
524 FlushInstructionCache (current_process
, memaddr
, len
);
528 ReadProcessMemory (current_process
, memaddr
, our
, len
, &done
);
534 child_kill_inferior (void)
536 CHECK (TerminateProcess (current_process
, 0));
537 CHECK (CloseHandle (current_process
));
538 CHECK (CloseHandle (current_thread
));
542 child_resume (int pid
, int step
, enum target_signal signal
)
544 DEBUG (("child_resume (%d, %d, %d);\n", pid
, step
, signal
));
548 /* Single step by setting t bit */
549 child_fetch_inferior_registers (PS_REGNUM
);
550 context
.EFlags
|= FLAG_TRACE_BIT
;
553 if (context
.ContextFlags
)
555 CHECK (SetThreadContext (current_thread
, &context
));
556 context
.ContextFlags
= 0;
561 fprintf_unfiltered (gdb_stderr
, "Can't send signals to the child.\n");
564 CHECK (ContinueDebugEvent (current_process_id
,
570 child_prepare_to_store ()
572 /* Do nothing, since we can store individual regs */
586 struct target_ops child_ops
=
588 "child", /* to_shortname */
589 "Win32 child process", /* to_longname */
590 "Win32 child process (started by the \"run\" command).", /* to_doc */
591 child_open
, /* to_open */
592 child_close
, /* to_close */
593 child_attach
, /* to_attach */
594 child_detach
, /* to_detach */
595 child_resume
, /* to_resume */
596 child_wait
, /* to_wait */
597 child_fetch_inferior_registers
,/* to_fetch_registers */
598 child_store_inferior_registers
,/* to_store_registers */
599 child_prepare_to_store
, /* to_child_prepare_to_store */
600 child_xfer_memory
, /* to_xfer_memory */
601 child_files_info
, /* to_files_info */
602 memory_insert_breakpoint
, /* to_insert_breakpoint */
603 memory_remove_breakpoint
, /* to_remove_breakpoint */
604 terminal_init_inferior
, /* to_terminal_init */
605 terminal_inferior
, /* to_terminal_inferior */
606 terminal_ours_for_output
, /* to_terminal_ours_for_output */
607 terminal_ours
, /* to_terminal_ours */
608 child_terminal_info
, /* to_terminal_info */
609 child_kill_inferior
, /* to_kill */
611 0, /* to_lookup_symbol */
612 child_create_inferior
, /* to_create_inferior */
613 child_mourn_inferior
, /* to_mourn_inferior */
614 child_can_run
, /* to_can_run */
615 0, /* to_notice_signals */
616 0, /* to_thread_alive */
617 child_stop
, /* to_stop */
618 process_stratum
, /* to_stratum */
620 1, /* to_has_all_memory */
621 1, /* to_has_memory */
622 1, /* to_has_stack */
623 1, /* to_has_registers */
624 1, /* to_has_execution */
626 0, /* to_sections_end */
627 OPS_MAGIC
/* to_magic */
631 _initialize_inftarg ()
634 (add_set_cmd ("new-console", class_support
, var_boolean
,
635 (char *) &new_console
,
636 "Set creation of new console when creating child process.",
641 (add_set_cmd ("new-group", class_support
, var_boolean
,
643 "Set creation of new group when creating child process.",
647 add_target (&child_ops
);