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