]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/win32-nat.c
Fixed .Sanitize
[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"
1ef980b9
SC
36#include "symfile.h"
37#include "objfiles.h"
24e60978 38#include "gdb_string.h"
fdfa3315 39#include "gdbthread.h"
24e60978 40#include "gdbcmd.h"
1750a5ef 41#include <sys/param.h>
24e60978 42
1ef980b9
SC
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
24e60978
SC
48
49/* Forward declaration */
50extern struct target_ops child_ops;
51
52/* The most recently read context. Inspect ContextFlags to see what
53 bits are valid. */
54
55static CONTEXT context;
56
57/* The process and thread handles for the above context. */
58
59static HANDLE current_process;
60static HANDLE current_thread;
61static int current_process_id;
62static int current_thread_id;
63
64/* Counts of things. */
65static int exception_count = 0;
66static int event_count = 0;
67
68/* User options. */
69static int new_console = 0;
70static int new_group = 0;
1ef980b9
SC
71static int dos_path_style = 0;
72static int debug_exec = 0; /* show execution */
73static int debug_events = 0; /* show events from kernel */
74static int debug_memory = 0; /* show target memory accesses */
75static int debug_exceptions = 0; /* show target exceptions */
24e60978
SC
76
77/* This vector maps GDB's idea of a register's number into an address
78 in the win32 exception context vector.
79
80 It also contains the bit mask needed to load the register in question.
81
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
88 out bit. */
89
90struct regmappings
91 {
92 char *incontext;
93 int mask;
94 };
95
454ffae5
SC
96
97static const struct regmappings mappings[] =
24e60978 98{
454ffae5
SC
99#ifdef __PPC__
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},
108
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},
117
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},
126
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},
135
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},
144
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},
153
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},
162
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},
171
172
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},
178
179 {(char *) &context.Xer, CONTEXT_INTEGER},
180 {0,0}, /* MQ, but there isn't one */
181#else
24e60978
SC
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},
454ffae5 206#endif
24e60978
SC
207};
208
209
210/* This vector maps the target's idea of an exception (extracted
211 from the DEBUG_EVENT structure) to GDB's idea. */
212
213struct xlate_exception
214 {
215 int them;
216 enum target_signal us;
217 };
218
219
220static const struct xlate_exception
221 xlate[] =
222{
223 {EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV},
9cbf6c0e 224 {STATUS_STACK_OVERFLOW, TARGET_SIGNAL_SEGV},
24e60978
SC
225 {EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP},
226 {DBG_CONTROL_C, TARGET_SIGNAL_INT},
227 {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP},
228 {-1, -1}};
229
230
231static void
232check (BOOL ok, const char *file, int line)
233{
234 if (!ok)
235 printf_filtered ("error return %s:%d was %d\n", file, line, GetLastError ());
236}
237
238static void
239child_fetch_inferior_registers (int r)
240{
241 if (r < 0)
242 {
243 for (r = 0; r < NUM_REGS; r++)
244 child_fetch_inferior_registers (r);
245 }
246 else
247 {
248 supply_register (r, mappings[r].incontext);
249 }
250}
251
252static void
253child_store_inferior_registers (int r)
254{
255 if (r < 0)
256 {
257 for (r = 0; r < NUM_REGS; r++)
258 child_store_inferior_registers (r);
259 }
260 else
261 {
262 read_register_gen (r, mappings[r].incontext);
263 }
264}
265
266
267/* Wait for child to do something. Return pid of child, or -1 in case
268 of error; store status through argument pointer OURSTATUS. */
269
270
1750a5ef
SC
271static int
272handle_load_dll (char *eventp)
24e60978 273{
1750a5ef 274 DEBUG_EVENT * event = (DEBUG_EVENT *)eventp;
24e60978
SC
275 DWORD dll_name_ptr;
276 DWORD done;
277
278 ReadProcessMemory (current_process,
279 (DWORD) event->u.LoadDll.lpImageName,
280 (char *) &dll_name_ptr,
281 sizeof (dll_name_ptr), &done);
282
283 /* See if we could read the address of a string, and that the
284 address isn't null. */
285
286 if (done == sizeof (dll_name_ptr) && dll_name_ptr)
287 {
1ef980b9
SC
288 char *dll_name, *dll_basename;
289 struct objfile *objfile;
290 char unix_dll_name[MAX_PATH];
24e60978
SC
291 int size = event->u.LoadDll.fUnicode ? sizeof (WCHAR) : sizeof (char);
292 int len = 0;
293 char b[2];
294 do
295 {
296 ReadProcessMemory (current_process,
297 dll_name_ptr + len * size,
298 &b,
299 size,
300 &done);
301 len++;
302 }
303 while ((b[0] != 0 || b[size - 1] != 0) && done == size);
304
24e60978
SC
305 dll_name = alloca (len);
306
307 if (event->u.LoadDll.fUnicode)
308 {
309 WCHAR *unicode_dll_name = (WCHAR *) alloca (len * sizeof (WCHAR));
310 ReadProcessMemory (current_process,
311 dll_name_ptr,
312 unicode_dll_name,
313 len * sizeof (WCHAR),
314 &done);
315
316 WideCharToMultiByte (CP_ACP, 0,
317 unicode_dll_name, len,
318 dll_name, len, 0, 0);
319 }
320 else
321 {
322 ReadProcessMemory (current_process,
323 dll_name_ptr,
324 dll_name,
325 len,
326 &done);
327 }
328
1ef980b9
SC
329
330 dos_path_to_unix_path (dll_name, unix_dll_name);
331
24e60978
SC
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. */
334
1ef980b9
SC
335 if (!(dll_basename = strrchr(dll_name, '\\')))
336 dll_basename = strrchr(dll_name, '/');
337
338 ALL_OBJFILES(objfile)
339 {
340 char *objfile_basename;
341 if (!(objfile_basename = strrchr(objfile->name, '\\')))
342 objfile_basename = strrchr(objfile->name, '/');
343
344 if (dll_basename && objfile_basename &&
345 strcmp(dll_basename+1, objfile_basename+1) == 0)
346 {
347 printf_unfiltered ("%s (symbols previously loaded)\n",
348 dll_basename + 1);
349 return 1;
350 }
351 }
352
353
354 context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
24e60978
SC
355 GetThreadContext (current_thread, &context);
356
1750a5ef
SC
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.
360
361 FIXME: Is this the real reason that we need the 0x1000 ? */
362
363
1ef980b9 364 symbol_file_add (unix_dll_name, 0,
1750a5ef 365 (int) event->u.LoadDll.lpBaseOfDll + 0x1000, 0, 0, 0);
24e60978 366
1ef980b9
SC
367 printf_unfiltered ("%x:%s\n", event->u.LoadDll.lpBaseOfDll,
368 unix_dll_name);
24e60978 369 }
1750a5ef 370 return 1;
24e60978
SC
371}
372
373
374static void
375handle_exception (DEBUG_EVENT * event, struct target_waitstatus *ourstatus)
376{
377 int i;
378 int done = 0;
379 ourstatus->kind = TARGET_WAITKIND_STOPPED;
380
24e60978 381
1ef980b9 382 switch (event->u.Exception.ExceptionRecord.ExceptionCode)
24e60978 383 {
1ef980b9
SC
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;
388 break;
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;
393 break;
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;
398 break;
399 case DBG_CONTROL_C:
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;
403 break;
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;
408 break;
409 default:
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);
24e60978 413 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
1ef980b9 414 break;
24e60978 415 }
1ef980b9 416 context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
24e60978
SC
417 GetThreadContext (current_thread, &context);
418 exception_count++;
419}
420
421static int
422child_wait (int pid, struct target_waitstatus *ourstatus)
423{
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. */
429
430 while (1)
431 {
432 DEBUG_EVENT event;
433 BOOL t = WaitForDebugEvent (&event, INFINITE);
1ef980b9 434 char *p;
24e60978
SC
435
436 event_count++;
437
438 current_thread_id = event.dwThreadId;
439 current_process_id = event.dwProcessId;
440
441 switch (event.dwDebugEventCode)
442 {
443 case CREATE_THREAD_DEBUG_EVENT:
1ef980b9
SC
444 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
445 event.dwProcessId, event.dwThreadId,
446 "CREATE_THREAD_DEBUG_EVENT"));
447 break;
24e60978 448 case EXIT_THREAD_DEBUG_EVENT:
1ef980b9
SC
449 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
450 event.dwProcessId, event.dwThreadId,
451 "EXIT_THREAD_DEBUG_EVENT"));
452 break;
24e60978 453 case CREATE_PROCESS_DEBUG_EVENT:
1ef980b9
SC
454 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
455 event.dwProcessId, event.dwThreadId,
456 "CREATE_PROCESS_DEBUG_EVENT"));
24e60978
SC
457 break;
458
459 case EXIT_PROCESS_DEBUG_EVENT:
1ef980b9
SC
460 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
461 event.dwProcessId, event.dwThreadId,
462 "EXIT_PROCESS_DEBUG_EVENT"));
24e60978
SC
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;
468 break;
469
470 case LOAD_DLL_DEBUG_EVENT:
1ef980b9
SC
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,
475 (char*) &event,
476 "\n[failed reading symbols from DLL]\n",
477 RETURN_MASK_ALL);
478 registers_changed(); /* mark all regs invalid */
24e60978 479 break;
1ef980b9
SC
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"));
24e60978
SC
489 handle_exception (&event, ourstatus);
490 return current_process_id;
1ef980b9
SC
491
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)
499 {
500 warning(p);
501 free(p);
502 }
503 break;
24e60978 504 default:
1ef980b9
SC
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);
24e60978
SC
509 break;
510 }
1ef980b9
SC
511 DEBUG_EVENTS (("ContinueDebugEvent (cpid=%d, ctid=%d, DBG_CONTINUE);\n",
512 current_process_id, current_thread_id));
24e60978
SC
513 CHECK (ContinueDebugEvent (current_process_id,
514 current_thread_id,
515 DBG_CONTINUE));
516 }
517}
518
519
24e60978
SC
520/* Attach to process PID, then initialize for debugging it. */
521
522static void
523child_attach (args, from_tty)
524 char *args;
525 int from_tty;
526{
527 BOOL ok;
528
529 if (!args)
530 error_no_arg ("process-id to attach");
531
532 current_process_id = strtoul (args, 0, 0);
533
534 ok = DebugActiveProcess (current_process_id);
535
536 if (!ok)
537 error ("Can't attach to process.");
538
539
540 exception_count = 0;
541 event_count = 0;
542
543 if (from_tty)
544 {
545 char *exec_file = (char *) get_exec_file (0);
546
547 if (exec_file)
548 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
549 target_pid_to_str (current_process_id));
550 else
551 printf_unfiltered ("Attaching to %s\n",
552 target_pid_to_str (current_process_id));
553
554 gdb_flush (gdb_stdout);
555 }
556
557 inferior_pid = current_process_id;
558 push_target (&child_ops);
559}
560
561
562static void
563child_detach (args, from_tty)
564 char *args;
565 int from_tty;
566{
567 if (from_tty)
568 {
569 char *exec_file = get_exec_file (0);
570 if (exec_file == 0)
571 exec_file = "";
572 printf_unfiltered ("Detaching from program: %s %s\n", exec_file,
573 target_pid_to_str (inferior_pid));
574 gdb_flush (gdb_stdout);
575 }
576 inferior_pid = 0;
577 unpush_target (&child_ops);
578}
579
580
581/* Print status information about what we're accessing. */
582
583static void
584child_files_info (ignore)
585 struct target_ops *ignore;
586{
587 printf_unfiltered ("\tUsing the running image of %s %s.\n",
588 attach_flag ? "attached" : "child", target_pid_to_str (inferior_pid));
589}
590
591/* ARGSUSED */
592static void
593child_open (arg, from_tty)
594 char *arg;
595 int from_tty;
596{
597 error ("Use the \"run\" command to start a Unix child process.");
598}
599
24e60978 600
1ef980b9
SC
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. */
605
606static char *buf = NULL;
607static int blen = 2000;
608
609static char *
610unix_paths_to_dos_paths(char *newenv)
611{
612 int ei;
613 char *src;
614
615 if (buf == 0)
616 buf = (char *) malloc(blen);
617
618 if (newenv == 0 || *newenv == 0 ||
619 (src = strchr(newenv, '=')) == 0) /* find the equals sign */
620 return 0;
621
622 src++; /* now skip past it */
623
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;
631
632 memcpy(buf, newenv, len);
633 /* Split out the colons */
634 while (1)
635 {
636 char *tok = strchr (src, ':');
637 int doff = dir - buf;
638
639 if (doff + MAX_PATH > blen)
640 {
641 blen *= 2;
642 buf = (char *) realloc((void *) buf, blen);
643 dir = buf + doff;
644 }
645 if (tok)
646 {
647 *tok = 0;
648 cygwin32_unix_path_to_dos_path_keep_rel (src, dir);
649 *tok = ':';
650 dir += strlen(dir);
651 src = tok + 1;
652 *dir++ = ';';
653 }
654 else
655 {
656 cygwin32_unix_path_to_dos_path_keep_rel (src, dir);
657 dir += strlen(dir);
658 *dir++ = 0;
659 break;
660 }
661 }
662 return buf;
663 }
664 return 0;
665}
666
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. */
671
672static char *
673dos_paths_to_unix_paths(char *newenv)
674{
675 int ei;
676 char *src;
677
678 if (buf == 0)
679 buf = (char *) malloc(blen);
680
681 if (newenv == 0 || *newenv == 0 ||
682 (src = strchr(newenv, '=')) == 0) /* find the equals sign */
683 return 0;
684
685 src++; /* now skip past it */
686
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;
695
696 memcpy(buf, newenv, len);
697 /* Split out the colons */
698 while (1)
699 {
700 char *tok = strchr (src, ';');
701 int doff = dir - buf;
702
703 if (doff + MAX_PATH > blen)
704 {
705 blen *= 2;
706 buf = (char *) realloc((void *) buf, blen);
707 dir = buf + doff;
708 }
709 if (tok)
710 {
711 *tok = 0;
712 cygwin32_dos_path_to_unix_path_keep_rel (src, dir);
713 *tok = ';';
714 dir += strlen(dir);
715 src = tok + 1;
716 *dir++ = ':';
717 }
718 else
719 {
720 cygwin32_dos_path_to_unix_path_keep_rel (src, dir);
721 dir += strlen(dir);
722 *dir++ = 0;
723 break;
724 }
725 }
726 return buf;
727 }
728 return 0;
729}
730
731
eb708f2e 732/* Start an inferior win32 child process and sets inferior_pid to its pid.
24e60978
SC
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(). */
736
24e60978
SC
737static void
738child_create_inferior (exec_file, allargs, env)
739 char *exec_file;
740 char *allargs;
741 char **env;
742{
1750a5ef
SC
743 char real_path[MAXPATHLEN];
744 char *winenv;
745 char *temp;
746 int envlen;
747 int i;
748
24e60978
SC
749 STARTUPINFO si;
750 PROCESS_INFORMATION pi;
751 struct target_waitstatus dummy;
752 BOOL ret;
753 DWORD flags;
eb708f2e 754 char *args;
24e60978
SC
755
756 if (!exec_file)
757 {
758 error ("No executable specified, use `target exec'.\n");
759 }
760
761 memset (&si, 0, sizeof (si));
762 si.cb = sizeof (si);
763
1750a5ef 764 unix_path_to_dos_path (exec_file, real_path);
24e60978 765
1ef980b9 766 flags = DEBUG_ONLY_THIS_PROCESS;
24e60978
SC
767
768 if (new_group)
769 flags |= CREATE_NEW_PROCESS_GROUP;
770
771 if (new_console)
772 flags |= CREATE_NEW_CONSOLE;
773
3d78f532
SC
774 args = alloca (strlen (real_path) + strlen (allargs) + 2);
775
776 strcpy (args, real_path);
eb708f2e 777
eb708f2e
SC
778 strcat (args, " ");
779 strcat (args, allargs);
780
1ef980b9 781#if 0
1750a5ef
SC
782 /* get total size for env strings */
783 for (envlen = 0, i = 0; env[i] && *env[i]; i++)
784 envlen += strlen(env[i]) + 1;
1ef980b9
SC
785#else
786 /* get total size for env strings */
787 for (envlen = 0, i = 0; env[i] && *env[i]; i++)
788 {
789#if 0
790 winenv = 0;
791#else
792 winenv = unix_paths_to_dos_paths(env[i]);
793#endif
794 envlen += winenv ? strlen(winenv) + 1 : strlen(env[i]) + 1;
795 }
796#endif
1750a5ef 797
1ef980b9 798 winenv = alloca(2 * envlen + 1); /* allocate new buffer */
1750a5ef 799
1ef980b9
SC
800 /* copy env strings into new buffer */
801 for (temp = winenv, i = 0; env[i] && *env[i]; i++)
802 {
803#if 0
804 char *p = 0;
805#else
806 char *p = unix_paths_to_dos_paths(env[i]);
807#endif
808 strcpy(temp, p ? p : env[i]);
809 temp += strlen(temp) + 1;
810 }
811#if 0
1750a5ef 812 /* copy env strings into new buffer */
3d78f532 813 for (temp = winenv, i = 0; env[i] && *env[i]; i++)
1750a5ef
SC
814 {
815 strcpy(temp, env[i]);
816 temp += strlen(temp) + 1;
817 }
1ef980b9
SC
818#endif
819
1750a5ef
SC
820 *temp = 0; /* final nil string to terminate new env */
821
1750a5ef 822 ret = CreateProcess (0,
3d78f532 823 args, /* command line */
24e60978
SC
824 NULL, /* Security */
825 NULL, /* thread */
826 TRUE, /* inherit handles */
827 flags, /* start flags */
1750a5ef 828 winenv,
24e60978
SC
829 NULL, /* current directory */
830 &si,
831 &pi);
832 if (!ret)
686941a9 833 error ("Error creating process %s, (error %d)\n", exec_file, GetLastError());
24e60978
SC
834
835 exception_count = 0;
836 event_count = 0;
837
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);
844 init_thread_list ();
845 init_wait_for_inferior ();
846 clear_proceed_status ();
847 target_terminal_init ();
848 target_terminal_inferior ();
849
850 /* Ignore the first trap */
851 child_wait (inferior_pid, &dummy);
852
853 proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
854}
855
856static void
857child_mourn_inferior ()
858{
859 unpush_target (&child_ops);
860 generic_mourn_inferior ();
861}
862
863
864/* Send a SIGINT to the process group. This acts just like the user typed a
865 ^C on the controlling terminal. */
866
867void
868child_stop ()
869{
1ef980b9 870 DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
24e60978 871 CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0));
1ef980b9 872 registers_changed(); /* refresh register state */
24e60978
SC
873}
874
875int
eb708f2e
SC
876child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
877 int write, struct target_ops *target)
24e60978
SC
878{
879 DWORD done;
880 if (write)
881 {
1ef980b9
SC
882 DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08x\n",
883 len, memaddr));
24e60978
SC
884 WriteProcessMemory (current_process, memaddr, our, len, &done);
885 FlushInstructionCache (current_process, memaddr, len);
886 }
887 else
888 {
1ef980b9
SC
889 DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08x\n",
890 len, memaddr));
24e60978
SC
891 ReadProcessMemory (current_process, memaddr, our, len, &done);
892 }
893 return done;
894}
895
896void
897child_kill_inferior (void)
898{
899 CHECK (TerminateProcess (current_process, 0));
900 CHECK (CloseHandle (current_process));
901 CHECK (CloseHandle (current_thread));
1ef980b9 902 target_mourn_inferior(); /* or just child_mourn_inferior? */
24e60978
SC
903}
904
905void
906child_resume (int pid, int step, enum target_signal signal)
907{
1ef980b9
SC
908 DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, signal=%d);\n",
909 pid, step, signal));
24e60978
SC
910
911 if (step)
912 {
454ffae5
SC
913#ifdef __PPC__
914 warning ("Single stepping not done.\n");
915#endif
1ef980b9 916#ifdef i386
24e60978
SC
917 /* Single step by setting t bit */
918 child_fetch_inferior_registers (PS_REGNUM);
919 context.EFlags |= FLAG_TRACE_BIT;
454ffae5 920#endif
24e60978
SC
921 }
922
923 if (context.ContextFlags)
924 {
925 CHECK (SetThreadContext (current_thread, &context));
926 context.ContextFlags = 0;
927 }
928
929 if (signal)
930 {
931 fprintf_unfiltered (gdb_stderr, "Can't send signals to the child.\n");
932 }
933
1ef980b9
SC
934 DEBUG_EVENTS (("gdb: ContinueDebugEvent (cpid=%d, ctid=%d, DBG_CONTINUE);\n",
935 current_process_id, current_thread_id));
24e60978
SC
936 CHECK (ContinueDebugEvent (current_process_id,
937 current_thread_id,
938 DBG_CONTINUE));
939}
940
941static void
942child_prepare_to_store ()
943{
944 /* Do nothing, since we can store individual regs */
945}
946
947static int
948child_can_run ()
949{
950 return 1;
951}
952
953static void
954child_close ()
955{
1ef980b9 956 DEBUG_EVENTS (("gdb: child_close, inferior_pid=%d\n", inferior_pid));
24e60978 957}
1ef980b9 958
24e60978
SC
959struct target_ops child_ops =
960{
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 */
983 0, /* to_load */
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 */
992 0, /* to_next */
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 */
998 0, /* to_sections */
999 0, /* to_sections_end */
1000 OPS_MAGIC /* to_magic */
1001};
1002
1ef980b9
SC
1003#include "environ.h"
1004
1005static void
1006set_pathstyle_dos(args, from_tty, c)
1007 char *args;
1008 int from_tty;
1009 struct cmd_list_element *c;
1010{
1011 char **vector = environ_vector(inferior_environ);
1012 char *thisvar;
1013 int dos = *(int *) c->var;
1014
1015 if (info_verbose)
1016 printf_unfiltered ("Change dos_path_style to %s\n", dos ? "true":"false");
1017
1018 while (vector && *vector)
1019 {
1020 if (dos)
1021 thisvar = unix_paths_to_dos_paths(*vector);
1022 else
1023 thisvar = dos_paths_to_unix_paths(*vector);
1024
1025 if (thisvar)
1026 {
1027 if (info_verbose)
1028 printf_unfiltered ("Change %s\nto %s\n", *vector, thisvar);
1029 free(*vector);
1030 *vector = xmalloc(strlen(thisvar) + 1);
1031 strcpy(*vector, thisvar);
1032 }
1033 vector++;
1034 }
1035}
1036
1037
24e60978
SC
1038void
1039_initialize_inftarg ()
1040{
1ef980b9
SC
1041 struct cmd_list_element *c;
1042
24e60978
SC
1043 add_show_from_set
1044 (add_set_cmd ("new-console", class_support, var_boolean,
1045 (char *) &new_console,
1046 "Set creation of new console when creating child process.",
1047 &setlist),
1048 &showlist);
1049
1050 add_show_from_set
1051 (add_set_cmd ("new-group", class_support, var_boolean,
1052 (char *) &new_group,
1053 "Set creation of new group when creating child process.",
1054 &setlist),
1055 &showlist);
1056
1ef980b9
SC
1057 add_show_from_set
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.",
1061 &setlist),
1062 &showlist);
1063
1064 c->function.sfunc = set_pathstyle_dos;
1065
1066 add_show_from_set
1067 (add_set_cmd ("debugexec", class_support, var_boolean,
1068 (char *) &debug_exec,
1069 "Set whether to display execution in child process.",
1070 &setlist),
1071 &showlist);
1072
1073 add_show_from_set
1074 (add_set_cmd ("debugevents", class_support, var_boolean,
1075 (char *) &debug_events,
1076 "Set whether to display kernel events in child process.",
1077 &setlist),
1078 &showlist);
1079
1080 add_show_from_set
1081 (add_set_cmd ("debugmemory", class_support, var_boolean,
1082 (char *) &debug_memory,
1083 "Set whether to display memory accesses in child process.",
1084 &setlist),
1085 &showlist);
1086
1087 add_show_from_set
1088 (add_set_cmd ("debugexceptions", class_support, var_boolean,
1089 (char *) &debug_exceptions,
1090 "Set whether to display kernel exceptions in child process.",
1091 &setlist),
1092 &showlist);
1093
24e60978
SC
1094 add_target (&child_ops);
1095}