* ch-valprint.c (chill_val_print): Remove call to calculate_array_length.
[deliverable/binutils-gdb.git] / gdb / win32-nat.c
1 /* Target-vector operations for controlling win32 child processes, for GDB.
2 Copyright 1995, 1996
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 "symfile.h"
37 #include "objfiles.h"
38 #include "gdb_string.h"
39 #include "thread.h"
40 #include "gdbcmd.h"
41 #include <sys/param.h>
42
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
48
49 /* Forward declaration */
50 extern struct target_ops child_ops;
51
52 /* The most recently read context. Inspect ContextFlags to see what
53 bits are valid. */
54
55 static CONTEXT context;
56
57 /* The process and thread handles for the above context. */
58
59 static HANDLE current_process;
60 static HANDLE current_thread;
61 static int current_process_id;
62 static int current_thread_id;
63
64 /* Counts of things. */
65 static int exception_count = 0;
66 static int event_count = 0;
67
68 /* User options. */
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 */
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
90 struct regmappings
91 {
92 char *incontext;
93 int mask;
94 };
95
96
97 static const struct regmappings mappings[] =
98 {
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
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},
206 #endif
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
213 struct xlate_exception
214 {
215 int them;
216 enum target_signal us;
217 };
218
219
220 static const struct xlate_exception
221 xlate[] =
222 {
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},
228 {-1, -1}};
229
230
231 static void
232 check (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
238 static void
239 child_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
252 static void
253 child_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
271 static int
272 handle_load_dll (char *eventp)
273 {
274 DEBUG_EVENT * event = (DEBUG_EVENT *)eventp;
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 {
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);
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
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
329
330 dos_path_to_unix_path (dll_name, unix_dll_name);
331
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
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;
355 GetThreadContext (current_thread, &context);
356
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
364 symbol_file_add (unix_dll_name, 0,
365 (int) event->u.LoadDll.lpBaseOfDll + 0x1000, 0, 0, 0);
366
367 printf_unfiltered ("%x:%s\n", event->u.LoadDll.lpBaseOfDll,
368 unix_dll_name);
369 }
370 return 1;
371 }
372
373
374 static void
375 handle_exception (DEBUG_EVENT * event, struct target_waitstatus *ourstatus)
376 {
377 int i;
378 int done = 0;
379 ourstatus->kind = TARGET_WAITKIND_STOPPED;
380
381
382 switch (event->u.Exception.ExceptionRecord.ExceptionCode)
383 {
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);
413 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
414 break;
415 }
416 context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
417 GetThreadContext (current_thread, &context);
418 exception_count++;
419 }
420
421 static int
422 child_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);
434 char *p;
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:
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;
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"));
452 break;
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"));
457 break;
458
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;
468 break;
469
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,
475 (char*) &event,
476 "\n[failed reading symbols from DLL]\n",
477 RETURN_MASK_ALL);
478 registers_changed(); /* mark all regs invalid */
479 break;
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;
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;
504 default:
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);
509 break;
510 }
511 DEBUG_EVENTS (("ContinueDebugEvent (cpid=%d, ctid=%d, DBG_CONTINUE);\n",
512 current_process_id, current_thread_id));
513 CHECK (ContinueDebugEvent (current_process_id,
514 current_thread_id,
515 DBG_CONTINUE));
516 }
517 }
518
519
520 /* Attach to process PID, then initialize for debugging it. */
521
522 static void
523 child_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
562 static void
563 child_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
583 static void
584 child_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 */
592 static void
593 child_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
600
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
606 static char *buf = NULL;
607 static int blen = 2000;
608
609 static char *
610 unix_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
672 static char *
673 dos_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
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(). */
736
737 static void
738 child_create_inferior (exec_file, allargs, env)
739 char *exec_file;
740 char *allargs;
741 char **env;
742 {
743 char real_path[MAXPATHLEN];
744 char *winenv;
745 char *temp;
746 int envlen;
747 int i;
748
749 STARTUPINFO si;
750 PROCESS_INFORMATION pi;
751 struct target_waitstatus dummy;
752 BOOL ret;
753 DWORD flags;
754 char *args;
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
764 unix_path_to_dos_path (exec_file, real_path);
765
766 flags = DEBUG_ONLY_THIS_PROCESS;
767
768 if (new_group)
769 flags |= CREATE_NEW_PROCESS_GROUP;
770
771 if (new_console)
772 flags |= CREATE_NEW_CONSOLE;
773
774 args = alloca (strlen (real_path) + strlen (allargs) + 2);
775
776 strcpy (args, real_path);
777
778 strcat (args, " ");
779 strcat (args, allargs);
780
781 #if 0
782 /* get total size for env strings */
783 for (envlen = 0, i = 0; env[i] && *env[i]; i++)
784 envlen += strlen(env[i]) + 1;
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
797
798 winenv = alloca(2 * envlen + 1); /* allocate new buffer */
799
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
812 /* copy env strings into new buffer */
813 for (temp = winenv, i = 0; env[i] && *env[i]; i++)
814 {
815 strcpy(temp, env[i]);
816 temp += strlen(temp) + 1;
817 }
818 #endif
819
820 *temp = 0; /* final nil string to terminate new env */
821
822 ret = CreateProcess (0,
823 args, /* command line */
824 NULL, /* Security */
825 NULL, /* thread */
826 TRUE, /* inherit handles */
827 flags, /* start flags */
828 winenv,
829 NULL, /* current directory */
830 &si,
831 &pi);
832 if (!ret)
833 error ("Error creating process %s, (error %d)\n", exec_file, GetLastError());
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
856 static void
857 child_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
867 void
868 child_stop ()
869 {
870 DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
871 CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0));
872 registers_changed(); /* refresh register state */
873 }
874
875 int
876 child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
877 int write, struct target_ops *target)
878 {
879 DWORD done;
880 if (write)
881 {
882 DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08x\n",
883 len, memaddr));
884 WriteProcessMemory (current_process, memaddr, our, len, &done);
885 FlushInstructionCache (current_process, memaddr, len);
886 }
887 else
888 {
889 DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08x\n",
890 len, memaddr));
891 ReadProcessMemory (current_process, memaddr, our, len, &done);
892 }
893 return done;
894 }
895
896 void
897 child_kill_inferior (void)
898 {
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? */
903 }
904
905 void
906 child_resume (int pid, int step, enum target_signal signal)
907 {
908 DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, signal=%d);\n",
909 pid, step, signal));
910
911 if (step)
912 {
913 #ifdef __PPC__
914 warning ("Single stepping not done.\n");
915 #endif
916 #ifdef i386
917 /* Single step by setting t bit */
918 child_fetch_inferior_registers (PS_REGNUM);
919 context.EFlags |= FLAG_TRACE_BIT;
920 #endif
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
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,
937 current_thread_id,
938 DBG_CONTINUE));
939 }
940
941 static void
942 child_prepare_to_store ()
943 {
944 /* Do nothing, since we can store individual regs */
945 }
946
947 static int
948 child_can_run ()
949 {
950 return 1;
951 }
952
953 static void
954 child_close ()
955 {
956 DEBUG_EVENTS (("gdb: child_close, inferior_pid=%d\n", inferior_pid));
957 }
958
959 struct 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
1003 #include "environ.h"
1004
1005 static void
1006 set_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
1038 void
1039 _initialize_inftarg ()
1040 {
1041 struct cmd_list_element *c;
1042
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
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
1094 add_target (&child_ops);
1095 }
This page took 0.06635 seconds and 4 git commands to generate.