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>
38 #include "gdb_string.h"
39 #include "gdbthread.h"
41 #include <sys/param.h>
43 #define CHECK(x) check (x, __FILE__,__LINE__)
44 #define DEBUG_EXEC(x) if (debug_exec) printf x
45 #define DEBUG_EVENTS(x) if (debug_events) printf x
46 #define DEBUG_MEM(x) if (debug_memory) printf x
47 #define DEBUG_EXCEPT(x) if (debug_exceptions) printf x
49 /* Forward declaration */
50 extern struct target_ops child_ops
;
52 /* The most recently read context. Inspect ContextFlags to see what
55 static CONTEXT context
;
57 /* The process and thread handles for the above context. */
59 static HANDLE current_process
;
60 static HANDLE current_thread
;
61 static int current_process_id
;
62 static int current_thread_id
;
64 /* Counts of things. */
65 static int exception_count
= 0;
66 static int event_count
= 0;
69 static int new_console
= 0;
70 static int new_group
= 0;
71 static int dos_path_style
= 0;
72 static int debug_exec
= 0; /* show execution */
73 static int debug_events
= 0; /* show events from kernel */
74 static int debug_memory
= 0; /* show target memory accesses */
75 static int debug_exceptions
= 0; /* show target exceptions */
77 /* This vector maps GDB's idea of a register's number into an address
78 in the win32 exception context vector.
80 It also contains the bit mask needed to load the register in question.
82 One day we could read a reg, we could inspect the context we
83 already have loaded, if it doesn't have the bit set that we need,
84 we read that set of registers in using GetThreadContext. If the
85 context already contains what we need, we just unpack it. Then to
86 write a register, first we have to ensure that the context contains
87 the other regs of the group, and then we copy the info in and set
97 static const struct regmappings mappings
[] =
100 {(char *) &context
.Gpr0
, CONTEXT_INTEGER
},
101 {(char *) &context
.Gpr1
, CONTEXT_INTEGER
},
102 {(char *) &context
.Gpr2
, CONTEXT_INTEGER
},
103 {(char *) &context
.Gpr3
, CONTEXT_INTEGER
},
104 {(char *) &context
.Gpr4
, CONTEXT_INTEGER
},
105 {(char *) &context
.Gpr5
, CONTEXT_INTEGER
},
106 {(char *) &context
.Gpr6
, CONTEXT_INTEGER
},
107 {(char *) &context
.Gpr7
, CONTEXT_INTEGER
},
109 {(char *) &context
.Gpr8
, CONTEXT_INTEGER
},
110 {(char *) &context
.Gpr9
, CONTEXT_INTEGER
},
111 {(char *) &context
.Gpr10
, CONTEXT_INTEGER
},
112 {(char *) &context
.Gpr11
, CONTEXT_INTEGER
},
113 {(char *) &context
.Gpr12
, CONTEXT_INTEGER
},
114 {(char *) &context
.Gpr13
, CONTEXT_INTEGER
},
115 {(char *) &context
.Gpr14
, CONTEXT_INTEGER
},
116 {(char *) &context
.Gpr15
, CONTEXT_INTEGER
},
118 {(char *) &context
.Gpr16
, CONTEXT_INTEGER
},
119 {(char *) &context
.Gpr17
, CONTEXT_INTEGER
},
120 {(char *) &context
.Gpr18
, CONTEXT_INTEGER
},
121 {(char *) &context
.Gpr19
, CONTEXT_INTEGER
},
122 {(char *) &context
.Gpr20
, CONTEXT_INTEGER
},
123 {(char *) &context
.Gpr21
, CONTEXT_INTEGER
},
124 {(char *) &context
.Gpr22
, CONTEXT_INTEGER
},
125 {(char *) &context
.Gpr23
, CONTEXT_INTEGER
},
127 {(char *) &context
.Gpr24
, CONTEXT_INTEGER
},
128 {(char *) &context
.Gpr25
, CONTEXT_INTEGER
},
129 {(char *) &context
.Gpr26
, CONTEXT_INTEGER
},
130 {(char *) &context
.Gpr27
, CONTEXT_INTEGER
},
131 {(char *) &context
.Gpr28
, CONTEXT_INTEGER
},
132 {(char *) &context
.Gpr29
, CONTEXT_INTEGER
},
133 {(char *) &context
.Gpr30
, CONTEXT_INTEGER
},
134 {(char *) &context
.Gpr31
, CONTEXT_INTEGER
},
136 {(char *) &context
.Fpr0
, CONTEXT_FLOATING_POINT
},
137 {(char *) &context
.Fpr1
, CONTEXT_FLOATING_POINT
},
138 {(char *) &context
.Fpr2
, CONTEXT_FLOATING_POINT
},
139 {(char *) &context
.Fpr3
, CONTEXT_FLOATING_POINT
},
140 {(char *) &context
.Fpr4
, CONTEXT_FLOATING_POINT
},
141 {(char *) &context
.Fpr5
, CONTEXT_FLOATING_POINT
},
142 {(char *) &context
.Fpr6
, CONTEXT_FLOATING_POINT
},
143 {(char *) &context
.Fpr7
, CONTEXT_FLOATING_POINT
},
145 {(char *) &context
.Fpr8
, CONTEXT_FLOATING_POINT
},
146 {(char *) &context
.Fpr9
, CONTEXT_FLOATING_POINT
},
147 {(char *) &context
.Fpr10
, CONTEXT_FLOATING_POINT
},
148 {(char *) &context
.Fpr11
, CONTEXT_FLOATING_POINT
},
149 {(char *) &context
.Fpr12
, CONTEXT_FLOATING_POINT
},
150 {(char *) &context
.Fpr13
, CONTEXT_FLOATING_POINT
},
151 {(char *) &context
.Fpr14
, CONTEXT_FLOATING_POINT
},
152 {(char *) &context
.Fpr15
, CONTEXT_FLOATING_POINT
},
154 {(char *) &context
.Fpr16
, CONTEXT_FLOATING_POINT
},
155 {(char *) &context
.Fpr17
, CONTEXT_FLOATING_POINT
},
156 {(char *) &context
.Fpr18
, CONTEXT_FLOATING_POINT
},
157 {(char *) &context
.Fpr19
, CONTEXT_FLOATING_POINT
},
158 {(char *) &context
.Fpr20
, CONTEXT_FLOATING_POINT
},
159 {(char *) &context
.Fpr21
, CONTEXT_FLOATING_POINT
},
160 {(char *) &context
.Fpr22
, CONTEXT_FLOATING_POINT
},
161 {(char *) &context
.Fpr23
, CONTEXT_FLOATING_POINT
},
163 {(char *) &context
.Fpr24
, CONTEXT_FLOATING_POINT
},
164 {(char *) &context
.Fpr25
, CONTEXT_FLOATING_POINT
},
165 {(char *) &context
.Fpr26
, CONTEXT_FLOATING_POINT
},
166 {(char *) &context
.Fpr27
, CONTEXT_FLOATING_POINT
},
167 {(char *) &context
.Fpr28
, CONTEXT_FLOATING_POINT
},
168 {(char *) &context
.Fpr29
, CONTEXT_FLOATING_POINT
},
169 {(char *) &context
.Fpr30
, CONTEXT_FLOATING_POINT
},
170 {(char *) &context
.Fpr31
, CONTEXT_FLOATING_POINT
},
173 {(char *) &context
.Iar
, CONTEXT_CONTROL
},
174 {(char *) &context
.Msr
, CONTEXT_CONTROL
},
175 {(char *) &context
.Cr
, CONTEXT_INTEGER
},
176 {(char *) &context
.Lr
, CONTEXT_CONTROL
},
177 {(char *) &context
.Ctr
, CONTEXT_CONTROL
},
179 {(char *) &context
.Xer
, CONTEXT_INTEGER
},
180 {0,0}, /* MQ, but there isn't one */
182 {(char *) &context
.Eax
, CONTEXT_INTEGER
},
183 {(char *) &context
.Ecx
, CONTEXT_INTEGER
},
184 {(char *) &context
.Edx
, CONTEXT_INTEGER
},
185 {(char *) &context
.Ebx
, CONTEXT_INTEGER
},
186 {(char *) &context
.Esp
, CONTEXT_CONTROL
},
187 {(char *) &context
.Ebp
, CONTEXT_CONTROL
},
188 {(char *) &context
.Esi
, CONTEXT_INTEGER
},
189 {(char *) &context
.Edi
, CONTEXT_INTEGER
},
190 {(char *) &context
.Eip
, CONTEXT_CONTROL
},
191 {(char *) &context
.EFlags
, CONTEXT_CONTROL
},
192 {(char *) &context
.SegCs
, CONTEXT_SEGMENTS
},
193 {(char *) &context
.SegSs
, CONTEXT_SEGMENTS
},
194 {(char *) &context
.SegDs
, CONTEXT_SEGMENTS
},
195 {(char *) &context
.SegEs
, CONTEXT_SEGMENTS
},
196 {(char *) &context
.SegFs
, CONTEXT_SEGMENTS
},
197 {(char *) &context
.SegGs
, CONTEXT_SEGMENTS
},
198 {&context
.FloatSave
.RegisterArea
[0 * 10], CONTEXT_FLOATING_POINT
},
199 {&context
.FloatSave
.RegisterArea
[1 * 10], CONTEXT_FLOATING_POINT
},
200 {&context
.FloatSave
.RegisterArea
[2 * 10], CONTEXT_FLOATING_POINT
},
201 {&context
.FloatSave
.RegisterArea
[3 * 10], CONTEXT_FLOATING_POINT
},
202 {&context
.FloatSave
.RegisterArea
[4 * 10], CONTEXT_FLOATING_POINT
},
203 {&context
.FloatSave
.RegisterArea
[5 * 10], CONTEXT_FLOATING_POINT
},
204 {&context
.FloatSave
.RegisterArea
[6 * 10], CONTEXT_FLOATING_POINT
},
205 {&context
.FloatSave
.RegisterArea
[7 * 10], CONTEXT_FLOATING_POINT
},
210 /* This vector maps the target's idea of an exception (extracted
211 from the DEBUG_EVENT structure) to GDB's idea. */
213 struct xlate_exception
216 enum target_signal us
;
220 static const struct xlate_exception
223 {EXCEPTION_ACCESS_VIOLATION
, TARGET_SIGNAL_SEGV
},
224 {STATUS_STACK_OVERFLOW
, TARGET_SIGNAL_SEGV
},
225 {EXCEPTION_BREAKPOINT
, TARGET_SIGNAL_TRAP
},
226 {DBG_CONTROL_C
, TARGET_SIGNAL_INT
},
227 {EXCEPTION_SINGLE_STEP
, TARGET_SIGNAL_TRAP
},
232 check (BOOL ok
, const char *file
, int line
)
235 printf_filtered ("error return %s:%d was %d\n", file
, line
, GetLastError ());
239 child_fetch_inferior_registers (int r
)
243 for (r
= 0; r
< NUM_REGS
; r
++)
244 child_fetch_inferior_registers (r
);
248 supply_register (r
, mappings
[r
].incontext
);
253 child_store_inferior_registers (int r
)
257 for (r
= 0; r
< NUM_REGS
; r
++)
258 child_store_inferior_registers (r
);
262 read_register_gen (r
, mappings
[r
].incontext
);
267 /* Wait for child to do something. Return pid of child, or -1 in case
268 of error; store status through argument pointer OURSTATUS. */
272 handle_load_dll (char *eventp
)
274 DEBUG_EVENT
* event
= (DEBUG_EVENT
*)eventp
;
278 ReadProcessMemory (current_process
,
279 (DWORD
) event
->u
.LoadDll
.lpImageName
,
280 (char *) &dll_name_ptr
,
281 sizeof (dll_name_ptr
), &done
);
283 /* See if we could read the address of a string, and that the
284 address isn't null. */
286 if (done
== sizeof (dll_name_ptr
) && dll_name_ptr
)
288 char *dll_name
, *dll_basename
;
289 struct objfile
*objfile
;
290 char unix_dll_name
[MAX_PATH
];
291 int size
= event
->u
.LoadDll
.fUnicode
? sizeof (WCHAR
) : sizeof (char);
296 ReadProcessMemory (current_process
,
297 dll_name_ptr
+ len
* size
,
303 while ((b
[0] != 0 || b
[size
- 1] != 0) && done
== size
);
305 dll_name
= alloca (len
);
307 if (event
->u
.LoadDll
.fUnicode
)
309 WCHAR
*unicode_dll_name
= (WCHAR
*) alloca (len
* sizeof (WCHAR
));
310 ReadProcessMemory (current_process
,
313 len
* sizeof (WCHAR
),
316 WideCharToMultiByte (CP_ACP
, 0,
317 unicode_dll_name
, len
,
318 dll_name
, len
, 0, 0);
322 ReadProcessMemory (current_process
,
330 dos_path_to_unix_path (dll_name
, unix_dll_name
);
332 /* FIXME!! It would be nice to define one symbol which pointed to the
333 front of the dll if we can't find any symbols. */
335 if (!(dll_basename
= strrchr(dll_name
, '\\')))
336 dll_basename
= strrchr(dll_name
, '/');
338 ALL_OBJFILES(objfile
)
340 char *objfile_basename
;
341 if (!(objfile_basename
= strrchr(objfile
->name
, '\\')))
342 objfile_basename
= strrchr(objfile
->name
, '/');
344 if (dll_basename
&& objfile_basename
&&
345 strcmp(dll_basename
+1, objfile_basename
+1) == 0)
347 printf_unfiltered ("%s (symbols previously loaded)\n",
354 context
.ContextFlags
= CONTEXT_FULL
| CONTEXT_FLOATING_POINT
;
355 GetThreadContext (current_thread
, &context
);
357 /* The symbols in a dll are offset by 0x1000, which is the
358 the offset from 0 of the first byte in an image - because
359 of the file header and the section alignment.
361 FIXME: Is this the real reason that we need the 0x1000 ? */
364 symbol_file_add (unix_dll_name
, 0,
365 (int) event
->u
.LoadDll
.lpBaseOfDll
+ 0x1000, 0, 0, 0);
367 printf_unfiltered ("%x:%s\n", event
->u
.LoadDll
.lpBaseOfDll
,
375 handle_exception (DEBUG_EVENT
* event
, struct target_waitstatus
*ourstatus
)
379 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
382 switch (event
->u
.Exception
.ExceptionRecord
.ExceptionCode
)
384 case EXCEPTION_ACCESS_VIOLATION
:
385 DEBUG_EXCEPT (("gdb: Target exception ACCESS_VIOLATION at 0x%08x\n",
386 event
->u
.Exception
.ExceptionRecord
.ExceptionAddress
));
387 ourstatus
->value
.sig
= TARGET_SIGNAL_SEGV
;
389 case STATUS_STACK_OVERFLOW
:
390 DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08x\n",
391 event
->u
.Exception
.ExceptionRecord
.ExceptionAddress
));
392 ourstatus
->value
.sig
= TARGET_SIGNAL_SEGV
;
394 case EXCEPTION_BREAKPOINT
:
395 DEBUG_EXCEPT (("gdb: Target exception BREAKPOINT at 0x%08x\n",
396 event
->u
.Exception
.ExceptionRecord
.ExceptionAddress
));
397 ourstatus
->value
.sig
= TARGET_SIGNAL_TRAP
;
400 DEBUG_EXCEPT (("gdb: Target exception CONTROL_C at 0x%08x\n",
401 event
->u
.Exception
.ExceptionRecord
.ExceptionAddress
));
402 ourstatus
->value
.sig
= TARGET_SIGNAL_INT
;
404 case EXCEPTION_SINGLE_STEP
:
405 DEBUG_EXCEPT (("gdb: Target exception SINGLE_STEP at 0x%08x\n",
406 event
->u
.Exception
.ExceptionRecord
.ExceptionAddress
));
407 ourstatus
->value
.sig
= TARGET_SIGNAL_TRAP
;
410 printf_unfiltered ("gdb: unknown target exception 0x%08x at 0x%08x\n",
411 event
->u
.Exception
.ExceptionRecord
.ExceptionCode
,
412 event
->u
.Exception
.ExceptionRecord
.ExceptionAddress
);
413 ourstatus
->value
.sig
= TARGET_SIGNAL_UNKNOWN
;
416 context
.ContextFlags
= CONTEXT_FULL
| CONTEXT_FLOATING_POINT
;
417 GetThreadContext (current_thread
, &context
);
422 child_wait (int pid
, struct target_waitstatus
*ourstatus
)
424 /* We loop when we get a non-standard exception rather than return
425 with a SPURIOUS because resume can try and step or modify things,
426 which needs a current_thread. But some of these exceptions mark
427 the birth or death of threads, which mean that the current thread
428 isn't necessarily what you think it is. */
433 BOOL t
= WaitForDebugEvent (&event
, INFINITE
);
438 current_thread_id
= event
.dwThreadId
;
439 current_process_id
= event
.dwProcessId
;
441 switch (event
.dwDebugEventCode
)
443 case CREATE_THREAD_DEBUG_EVENT
:
444 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
445 event
.dwProcessId
, event
.dwThreadId
,
446 "CREATE_THREAD_DEBUG_EVENT"));
448 case EXIT_THREAD_DEBUG_EVENT
:
449 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
450 event
.dwProcessId
, event
.dwThreadId
,
451 "EXIT_THREAD_DEBUG_EVENT"));
453 case CREATE_PROCESS_DEBUG_EVENT
:
454 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
455 event
.dwProcessId
, event
.dwThreadId
,
456 "CREATE_PROCESS_DEBUG_EVENT"));
459 case EXIT_PROCESS_DEBUG_EVENT
:
460 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
461 event
.dwProcessId
, event
.dwThreadId
,
462 "EXIT_PROCESS_DEBUG_EVENT"));
463 ourstatus
->kind
= TARGET_WAITKIND_EXITED
;
464 ourstatus
->value
.integer
= event
.u
.ExitProcess
.dwExitCode
;
465 CloseHandle (current_process
);
466 CloseHandle (current_thread
);
467 return current_process_id
;
470 case LOAD_DLL_DEBUG_EVENT
:
471 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
472 event
.dwProcessId
, event
.dwThreadId
,
473 "LOAD_DLL_DEBUG_EVENT"));
474 catch_errors (handle_load_dll
,
476 "\n[failed reading symbols from DLL]\n",
478 registers_changed(); /* mark all regs invalid */
480 case UNLOAD_DLL_DEBUG_EVENT
:
481 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
482 event
.dwProcessId
, event
.dwThreadId
,
483 "UNLOAD_DLL_DEBUG_EVENT"));
484 break; /* FIXME: don't know what to do here */
485 case EXCEPTION_DEBUG_EVENT
:
486 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
487 event
.dwProcessId
, event
.dwThreadId
,
488 "EXCEPTION_DEBUG_EVENT"));
489 handle_exception (&event
, ourstatus
);
490 return current_process_id
;
492 case OUTPUT_DEBUG_STRING_EVENT
: /* message from the kernel */
493 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
494 event
.dwProcessId
, event
.dwThreadId
,
495 "OUTPUT_DEBUG_STRING_EVENT"));
496 if (target_read_string
497 ((CORE_ADDR
) event
.u
.DebugString
.lpDebugStringData
,
498 &p
, 1024, 0) && p
&& *p
)
505 printf_unfiltered ("gdb: kernel event for pid=%d tid=%d\n",
506 event
.dwProcessId
, event
.dwThreadId
);
507 printf_unfiltered (" unknown event code %d\n",
508 event
.dwDebugEventCode
);
511 DEBUG_EVENTS (("ContinueDebugEvent (cpid=%d, ctid=%d, DBG_CONTINUE);\n",
512 current_process_id
, current_thread_id
));
513 CHECK (ContinueDebugEvent (current_process_id
,
520 /* Attach to process PID, then initialize for debugging it. */
523 child_attach (args
, from_tty
)
530 error_no_arg ("process-id to attach");
532 current_process_id
= strtoul (args
, 0, 0);
534 ok
= DebugActiveProcess (current_process_id
);
537 error ("Can't attach to process.");
545 char *exec_file
= (char *) get_exec_file (0);
548 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file
,
549 target_pid_to_str (current_process_id
));
551 printf_unfiltered ("Attaching to %s\n",
552 target_pid_to_str (current_process_id
));
554 gdb_flush (gdb_stdout
);
557 inferior_pid
= current_process_id
;
558 push_target (&child_ops
);
563 child_detach (args
, from_tty
)
569 char *exec_file
= get_exec_file (0);
572 printf_unfiltered ("Detaching from program: %s %s\n", exec_file
,
573 target_pid_to_str (inferior_pid
));
574 gdb_flush (gdb_stdout
);
577 unpush_target (&child_ops
);
581 /* Print status information about what we're accessing. */
584 child_files_info (ignore
)
585 struct target_ops
*ignore
;
587 printf_unfiltered ("\tUsing the running image of %s %s.\n",
588 attach_flag
? "attached" : "child", target_pid_to_str (inferior_pid
));
593 child_open (arg
, from_tty
)
597 error ("Use the \"run\" command to start a Unix child process.");
601 /* Convert a unix-style set-of-paths (a colon-separated list of directory
602 paths with forward slashes) into the dos style (semicolon-separated
603 list with backward slashes), simultaneously undoing any translations
604 performed by the mount table. */
606 static char *buf
= NULL
;
607 static int blen
= 2000;
610 unix_paths_to_dos_paths(char *newenv
)
616 buf
= (char *) malloc(blen
);
618 if (newenv
== 0 || *newenv
== 0 ||
619 (src
= strchr(newenv
, '=')) == 0) /* find the equals sign */
622 src
++; /* now skip past it */
624 if (src
[0] == '/' || /* is this a unix style path? */
625 (src
[0] == '.' && src
[1] == '/') ||
626 (src
[0] == '.' && src
[1] == '.' && src
[2] == '/'))
627 { /* we accept that we will fail on a relative path like 'foo/mumble' */
628 /* Found an env name, turn from unix style into dos style */
629 int len
= src
- newenv
;
630 char *dir
= buf
+ len
;
632 memcpy(buf
, newenv
, len
);
633 /* Split out the colons */
636 char *tok
= strchr (src
, ':');
637 int doff
= dir
- buf
;
639 if (doff
+ MAX_PATH
> blen
)
642 buf
= (char *) realloc((void *) buf
, blen
);
648 cygwin32_unix_path_to_dos_path_keep_rel (src
, dir
);
656 cygwin32_unix_path_to_dos_path_keep_rel (src
, dir
);
667 /* Convert a dos-style set-of-paths (a semicolon-separated list with
668 backward slashes) into the dos style (colon-separated list of
669 directory paths with forward slashes), simultaneously undoing any
670 translations performed by the mount table. */
673 dos_paths_to_unix_paths(char *newenv
)
679 buf
= (char *) malloc(blen
);
681 if (newenv
== 0 || *newenv
== 0 ||
682 (src
= strchr(newenv
, '=')) == 0) /* find the equals sign */
685 src
++; /* now skip past it */
687 if (src
[0] == '\\' || /* is this a dos style path? */
688 (isalpha(src
[0]) && src
[1] == ':' && src
[2] == '\\') ||
689 (src
[0] == '.' && src
[1] == '\\') ||
690 (src
[0] == '.' && src
[1] == '.' && src
[2] == '\\'))
691 { /* we accept that we will fail on a relative path like 'foo\mumble' */
692 /* Found an env name, turn from dos style into unix style */
693 int len
= src
- newenv
;
694 char *dir
= buf
+ len
;
696 memcpy(buf
, newenv
, len
);
697 /* Split out the colons */
700 char *tok
= strchr (src
, ';');
701 int doff
= dir
- buf
;
703 if (doff
+ MAX_PATH
> blen
)
706 buf
= (char *) realloc((void *) buf
, blen
);
712 cygwin32_dos_path_to_unix_path_keep_rel (src
, dir
);
720 cygwin32_dos_path_to_unix_path_keep_rel (src
, dir
);
732 /* Start an inferior win32 child process and sets inferior_pid to its pid.
733 EXEC_FILE is the file to run.
734 ALLARGS is a string containing the arguments to the program.
735 ENV is the environment vector to pass. Errors reported with error(). */
738 child_create_inferior (exec_file
, allargs
, env
)
743 char real_path
[MAXPATHLEN
];
750 PROCESS_INFORMATION pi
;
751 struct target_waitstatus dummy
;
758 error ("No executable specified, use `target exec'.\n");
761 memset (&si
, 0, sizeof (si
));
764 unix_path_to_dos_path (exec_file
, real_path
);
766 flags
= DEBUG_ONLY_THIS_PROCESS
;
769 flags
|= CREATE_NEW_PROCESS_GROUP
;
772 flags
|= CREATE_NEW_CONSOLE
;
774 args
= alloca (strlen (real_path
) + strlen (allargs
) + 2);
776 strcpy (args
, real_path
);
779 strcat (args
, allargs
);
782 /* get total size for env strings */
783 for (envlen
= 0, i
= 0; env
[i
] && *env
[i
]; i
++)
784 envlen
+= strlen(env
[i
]) + 1;
786 /* get total size for env strings */
787 for (envlen
= 0, i
= 0; env
[i
] && *env
[i
]; i
++)
792 winenv
= unix_paths_to_dos_paths(env
[i
]);
794 envlen
+= winenv
? strlen(winenv
) + 1 : strlen(env
[i
]) + 1;
798 winenv
= alloca(2 * envlen
+ 1); /* allocate new buffer */
800 /* copy env strings into new buffer */
801 for (temp
= winenv
, i
= 0; env
[i
] && *env
[i
]; i
++)
806 char *p
= unix_paths_to_dos_paths(env
[i
]);
808 strcpy(temp
, p
? p
: env
[i
]);
809 temp
+= strlen(temp
) + 1;
812 /* copy env strings into new buffer */
813 for (temp
= winenv
, i
= 0; env
[i
] && *env
[i
]; i
++)
815 strcpy(temp
, env
[i
]);
816 temp
+= strlen(temp
) + 1;
820 *temp
= 0; /* final nil string to terminate new env */
822 ret
= CreateProcess (0,
823 args
, /* command line */
826 TRUE
, /* inherit handles */
827 flags
, /* start flags */
829 NULL
, /* current directory */
833 error ("Error creating process %s, (error %d)\n", exec_file
, GetLastError());
838 inferior_pid
= pi
.dwProcessId
;
839 current_process
= pi
.hProcess
;
840 current_thread
= pi
.hThread
;
841 current_process_id
= pi
.dwProcessId
;
842 current_thread_id
= pi
.dwThreadId
;
843 push_target (&child_ops
);
845 init_wait_for_inferior ();
846 clear_proceed_status ();
847 target_terminal_init ();
848 target_terminal_inferior ();
850 /* Ignore the first trap */
851 child_wait (inferior_pid
, &dummy
);
853 proceed ((CORE_ADDR
) - 1, TARGET_SIGNAL_0
, 0);
857 child_mourn_inferior ()
859 unpush_target (&child_ops
);
860 generic_mourn_inferior ();
864 /* Send a SIGINT to the process group. This acts just like the user typed a
865 ^C on the controlling terminal. */
870 DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
871 CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT
, 0));
872 registers_changed(); /* refresh register state */
876 child_xfer_memory (CORE_ADDR memaddr
, char *our
, int len
,
877 int write
, struct target_ops
*target
)
882 DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08x\n",
884 WriteProcessMemory (current_process
, memaddr
, our
, len
, &done
);
885 FlushInstructionCache (current_process
, memaddr
, len
);
889 DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08x\n",
891 ReadProcessMemory (current_process
, memaddr
, our
, len
, &done
);
897 child_kill_inferior (void)
899 CHECK (TerminateProcess (current_process
, 0));
900 CHECK (CloseHandle (current_process
));
901 CHECK (CloseHandle (current_thread
));
902 target_mourn_inferior(); /* or just child_mourn_inferior? */
906 child_resume (int pid
, int step
, enum target_signal signal
)
908 DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, signal=%d);\n",
914 warning ("Single stepping not done.\n");
917 /* Single step by setting t bit */
918 child_fetch_inferior_registers (PS_REGNUM
);
919 context
.EFlags
|= FLAG_TRACE_BIT
;
923 if (context
.ContextFlags
)
925 CHECK (SetThreadContext (current_thread
, &context
));
926 context
.ContextFlags
= 0;
931 fprintf_unfiltered (gdb_stderr
, "Can't send signals to the child.\n");
934 DEBUG_EVENTS (("gdb: ContinueDebugEvent (cpid=%d, ctid=%d, DBG_CONTINUE);\n",
935 current_process_id
, current_thread_id
));
936 CHECK (ContinueDebugEvent (current_process_id
,
942 child_prepare_to_store ()
944 /* Do nothing, since we can store individual regs */
956 DEBUG_EVENTS (("gdb: child_close, inferior_pid=%d\n", inferior_pid
));
959 struct target_ops child_ops
=
961 "child", /* to_shortname */
962 "Win32 child process", /* to_longname */
963 "Win32 child process (started by the \"run\" command).", /* to_doc */
964 child_open
, /* to_open */
965 child_close
, /* to_close */
966 child_attach
, /* to_attach */
967 child_detach
, /* to_detach */
968 child_resume
, /* to_resume */
969 child_wait
, /* to_wait */
970 child_fetch_inferior_registers
,/* to_fetch_registers */
971 child_store_inferior_registers
,/* to_store_registers */
972 child_prepare_to_store
, /* to_child_prepare_to_store */
973 child_xfer_memory
, /* to_xfer_memory */
974 child_files_info
, /* to_files_info */
975 memory_insert_breakpoint
, /* to_insert_breakpoint */
976 memory_remove_breakpoint
, /* to_remove_breakpoint */
977 terminal_init_inferior
, /* to_terminal_init */
978 terminal_inferior
, /* to_terminal_inferior */
979 terminal_ours_for_output
, /* to_terminal_ours_for_output */
980 terminal_ours
, /* to_terminal_ours */
981 child_terminal_info
, /* to_terminal_info */
982 child_kill_inferior
, /* to_kill */
984 0, /* to_lookup_symbol */
985 child_create_inferior
, /* to_create_inferior */
986 child_mourn_inferior
, /* to_mourn_inferior */
987 child_can_run
, /* to_can_run */
988 0, /* to_notice_signals */
989 0, /* to_thread_alive */
990 child_stop
, /* to_stop */
991 process_stratum
, /* to_stratum */
993 1, /* to_has_all_memory */
994 1, /* to_has_memory */
995 1, /* to_has_stack */
996 1, /* to_has_registers */
997 1, /* to_has_execution */
999 0, /* to_sections_end */
1000 OPS_MAGIC
/* to_magic */
1003 #include "environ.h"
1006 set_pathstyle_dos(args
, from_tty
, c
)
1009 struct cmd_list_element
*c
;
1011 char **vector
= environ_vector(inferior_environ
);
1013 int dos
= *(int *) c
->var
;
1016 printf_unfiltered ("Change dos_path_style to %s\n", dos
? "true":"false");
1018 while (vector
&& *vector
)
1021 thisvar
= unix_paths_to_dos_paths(*vector
);
1023 thisvar
= dos_paths_to_unix_paths(*vector
);
1028 printf_unfiltered ("Change %s\nto %s\n", *vector
, thisvar
);
1030 *vector
= xmalloc(strlen(thisvar
) + 1);
1031 strcpy(*vector
, thisvar
);
1039 _initialize_inftarg ()
1041 struct cmd_list_element
*c
;
1044 (add_set_cmd ("new-console", class_support
, var_boolean
,
1045 (char *) &new_console
,
1046 "Set creation of new console when creating child process.",
1051 (add_set_cmd ("new-group", class_support
, var_boolean
,
1052 (char *) &new_group
,
1053 "Set creation of new group when creating child process.",
1058 (c
= add_set_cmd ("dos-path-style", class_support
, var_boolean
,
1059 (char *) &dos_path_style
,
1060 "Set whether paths in child's environment are shown in dos style.",
1064 c
->function
.sfunc
= set_pathstyle_dos
;
1067 (add_set_cmd ("debugexec", class_support
, var_boolean
,
1068 (char *) &debug_exec
,
1069 "Set whether to display execution in child process.",
1074 (add_set_cmd ("debugevents", class_support
, var_boolean
,
1075 (char *) &debug_events
,
1076 "Set whether to display kernel events in child process.",
1081 (add_set_cmd ("debugmemory", class_support
, var_boolean
,
1082 (char *) &debug_memory
,
1083 "Set whether to display memory accesses in child process.",
1088 (add_set_cmd ("debugexceptions", class_support
, var_boolean
,
1089 (char *) &debug_exceptions
,
1090 "Set whether to display kernel exceptions in child process.",
1094 add_target (&child_ops
);