]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/windows-nat.c
This commit was generated by cvs2svn to track changes on a CVS vendor
[thirdparty/binutils-gdb.git] / gdb / windows-nat.c
CommitLineData
24e60978 1/* Target-vector operations for controlling win32 child processes, for GDB.
b5edcb45 2 Copyright 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
24e60978 3 Contributed by Cygnus Support.
e88c49c3 4
24e60978
SC
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without eve nthe implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
cad9cd60
GN
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20*/
24e60978
SC
21
22/* by Steve Chamberlain, sac@cygnus.com */
23
3cee93ac 24/* We assume we're being built with and will be used for cygwin. */
e88c49c3 25
24e60978
SC
26#include "defs.h"
27#include "frame.h" /* required by inferior.h */
28#include "inferior.h"
29#include "target.h"
30#include "wait.h"
31#include "gdbcore.h"
32#include "command.h"
33#include <signal.h>
34#include <sys/types.h>
35#include <fcntl.h>
cad9cd60
GN
36#include <stdlib.h>
37
38#ifdef _MSC_VER
28444bf3 39#include "windefs.h"
cad9cd60
GN
40#else /* other WIN32 compiler */
41#include <windows.h>
42#endif
43
24e60978 44#include "buildsym.h"
1ef980b9
SC
45#include "symfile.h"
46#include "objfiles.h"
24e60978 47#include "gdb_string.h"
fdfa3315 48#include "gdbthread.h"
24e60978 49#include "gdbcmd.h"
1750a5ef 50#include <sys/param.h>
e88c49c3 51#include <unistd.h>
24e60978 52
0714f9bf
SS
53/* The ui's event loop. */
54extern int (*ui_loop_hook) PARAMS ((int signo));
55
56/* If we're not using the old Cygwin header file set, define the
57 following which never should have been in the generic Win32 API
58 headers in the first place since they were our own invention... */
59#ifndef _GNU_H_WINDOWS_H
60#define FLAG_TRACE_BIT 0x100
61#define CONTEXT_DEBUGGER (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
62#endif
63
3cee93ac
CF
64/* The string sent by cygwin when it processes a signal.
65 FIXME: This should be in a cygwin include file. */
66#define CYGWIN_SIGNAL_STRING "cygwin: signal"
67
1ef980b9
SC
68#define CHECK(x) check (x, __FILE__,__LINE__)
69#define DEBUG_EXEC(x) if (debug_exec) printf x
70#define DEBUG_EVENTS(x) if (debug_events) printf x
71#define DEBUG_MEM(x) if (debug_memory) printf x
72#define DEBUG_EXCEPT(x) if (debug_exceptions) printf x
24e60978
SC
73
74/* Forward declaration */
75extern struct target_ops child_ops;
76
b607efe7 77static void child_stop PARAMS ((void));
bc8bd256 78static int win32_child_thread_alive PARAMS ((int));
0714f9bf 79void child_kill_inferior PARAMS ((void));
3cee93ac
CF
80
81static int last_sig = 0; /* Set if a signal was received from the
82 debugged process */
b607efe7 83
3cee93ac
CF
84/* Thread information structure used to track information that is
85 not available in gdb's thread structure. */
86typedef struct thread_info_struct
87{
88 struct thread_info_struct *next;
89 DWORD id;
90 HANDLE h;
91 char *name;
92 int suspend_count;
93 CONTEXT context;
94} thread_info;
24e60978 95
3cee93ac 96static thread_info thread_head = {NULL};
24e60978
SC
97
98/* The process and thread handles for the above context. */
99
3cee93ac
CF
100static DEBUG_EVENT current_event; /* The current debug event from
101 WaitForDebugEvent */
102static HANDLE current_process_handle; /* Currently executing process */
103static thread_info *current_thread; /* Info on currently selected thread */
104static DWORD main_thread_id; /* Thread ID of the main thread */
24e60978
SC
105
106/* Counts of things. */
107static int exception_count = 0;
108static int event_count = 0;
109
110/* User options. */
111static int new_console = 0;
112static int new_group = 0;
1ef980b9
SC
113static int debug_exec = 0; /* show execution */
114static int debug_events = 0; /* show events from kernel */
115static int debug_memory = 0; /* show target memory accesses */
116static int debug_exceptions = 0; /* show target exceptions */
24e60978
SC
117
118/* This vector maps GDB's idea of a register's number into an address
3cee93ac 119 in the win32 exception context vector.
24e60978 120
3cee93ac 121 It also contains the bit mask needed to load the register in question.
24e60978
SC
122
123 One day we could read a reg, we could inspect the context we
124 already have loaded, if it doesn't have the bit set that we need,
125 we read that set of registers in using GetThreadContext. If the
126 context already contains what we need, we just unpack it. Then to
127 write a register, first we have to ensure that the context contains
128 the other regs of the group, and then we copy the info in and set
129 out bit. */
130
3cee93ac
CF
131#define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
132static const int mappings[] =
24e60978 133{
3cee93ac
CF
134 context_offset(Eax),
135 context_offset(Ecx),
136 context_offset(Edx),
137 context_offset(Ebx),
138 context_offset(Esp),
139 context_offset(Ebp),
140 context_offset(Esi),
141 context_offset(Edi),
142 context_offset(Eip),
143 context_offset(EFlags),
144 context_offset(SegCs),
145 context_offset(SegSs),
146 context_offset(SegDs),
147 context_offset(SegEs),
148 context_offset(SegFs),
149 context_offset(SegGs),
150 context_offset(FloatSave.RegisterArea[0 * 10]),
151 context_offset(FloatSave.RegisterArea[1 * 10]),
152 context_offset(FloatSave.RegisterArea[2 * 10]),
153 context_offset(FloatSave.RegisterArea[3 * 10]),
154 context_offset(FloatSave.RegisterArea[4 * 10]),
155 context_offset(FloatSave.RegisterArea[5 * 10]),
156 context_offset(FloatSave.RegisterArea[6 * 10]),
157 context_offset(FloatSave.RegisterArea[7 * 10]),
24e60978
SC
158};
159
24e60978
SC
160/* This vector maps the target's idea of an exception (extracted
161 from the DEBUG_EVENT structure) to GDB's idea. */
162
163struct xlate_exception
164 {
165 int them;
166 enum target_signal us;
167 };
168
24e60978
SC
169static const struct xlate_exception
170 xlate[] =
171{
172 {EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV},
9cbf6c0e 173 {STATUS_STACK_OVERFLOW, TARGET_SIGNAL_SEGV},
24e60978
SC
174 {EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP},
175 {DBG_CONTROL_C, TARGET_SIGNAL_INT},
176 {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP},
177 {-1, -1}};
178
3cee93ac
CF
179/* Find a thread record given a thread id.
180 If get_context then also retrieve the context for this
181 thread. */
182static thread_info *
183thread_rec (DWORD id, int get_context)
24e60978 184{
3cee93ac
CF
185 thread_info *th;
186
187 for (th = &thread_head; (th = th->next) != NULL; )
188 if (th->id == id)
189 {
190 if (!th->suspend_count && get_context)
191 {
192 if (get_context > 0)
193 th->suspend_count = SuspendThread (th->h) + 1;
194 else if (get_context < 0)
195 th->suspend_count = -1;
196
197 th->context.ContextFlags = CONTEXT_DEBUGGER;
198 GetThreadContext (th->h, &th->context);
199 }
200 return th;
201 }
202
203 return NULL;
204}
205
206/* Add a thread to the thread list */
207static thread_info *
208child_add_thread(DWORD id, HANDLE h)
209{
210 thread_info *th;
211
212 if ((th = thread_rec (id, FALSE)))
213 return th;
214
215 th = (thread_info *) xmalloc (sizeof (*th));
216 memset(th, 0, sizeof (*th));
217 th->id = id;
218 th->h = h;
219 th->next = thread_head.next;
220 thread_head.next = th;
221 add_thread (id);
222 return th;
24e60978
SC
223}
224
3cee93ac
CF
225/* Clear out any old thread list and reintialize it to a
226 pristine state. */
24e60978 227static void
3cee93ac 228child_init_thread_list ()
24e60978 229{
3cee93ac
CF
230 thread_info *th = &thread_head;
231
232 DEBUG_EVENTS (("gdb: child_init_thread_list\n"));
233 init_thread_list ();
234 while (th->next != NULL)
24e60978 235 {
3cee93ac
CF
236 thread_info *here = th->next;
237 th->next = here->next;
238 (void) CloseHandle (here->h);
239 free (here);
24e60978 240 }
3cee93ac
CF
241}
242
243/* Delete a thread from the list of threads */
244static void
245child_delete_thread (DWORD id)
246{
247 thread_info *th;
248
249 if (info_verbose)
250 printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (id));
251 delete_thread (id);
252
253 for (th = &thread_head;
254 th->next != NULL && th->next->id != id;
255 th = th->next)
256 continue;
257
258 if (th->next != NULL)
24e60978 259 {
3cee93ac
CF
260 thread_info *here = th->next;
261 th->next = here->next;
262 CloseHandle (here->h);
263 free (here);
24e60978
SC
264 }
265}
266
267static void
3cee93ac
CF
268check (BOOL ok, const char *file, int line)
269{
270 if (!ok)
271 printf_filtered ("error return %s:%d was %d\n", file, line, GetLastError ());
272}
273
274static void
275do_child_fetch_inferior_registers (int r)
24e60978 276{
3cee93ac
CF
277 if (r >= 0)
278 supply_register (r, ((char *) &current_thread->context) + mappings[r]);
279 else
24e60978
SC
280 {
281 for (r = 0; r < NUM_REGS; r++)
3cee93ac 282 do_child_fetch_inferior_registers (r);
24e60978 283 }
3cee93ac
CF
284}
285
286static void
287child_fetch_inferior_registers (int r)
288{
289 current_thread = thread_rec (inferior_pid, TRUE);
290 do_child_fetch_inferior_registers (r);
291}
292
293static void
294do_child_store_inferior_registers (int r)
295{
296 if (r >= 0)
297 read_register_gen (r, ((char *) &current_thread->context) + mappings[r]);
24e60978
SC
298 else
299 {
3cee93ac
CF
300 for (r = 0; r < NUM_REGS; r++)
301 do_child_store_inferior_registers (r);
24e60978
SC
302 }
303}
304
3cee93ac
CF
305/* Store a new register value into the current thread context */
306static void
307child_store_inferior_registers (int r)
308{
309 current_thread = thread_rec (inferior_pid, TRUE);
310 do_child_store_inferior_registers (r);
311}
24e60978
SC
312
313/* Wait for child to do something. Return pid of child, or -1 in case
314 of error; store status through argument pointer OURSTATUS. */
315
1750a5ef 316static int
bc8bd256 317handle_load_dll (PTR dummy)
24e60978 318{
3cee93ac 319 LOAD_DLL_DEBUG_INFO * event = &current_event.u.LoadDll;
24e60978
SC
320 DWORD dll_name_ptr;
321 DWORD done;
3cee93ac
CF
322 char dll_buf[MAX_PATH + 1];
323 char *p, *dll_name = NULL, *dll_basename;
324 struct objfile *objfile;
325 MEMORY_BASIC_INFORMATION minfo;
326
327 dll_buf[0] = dll_buf[sizeof(dll_buf) - 1] = '\0';
328
329 /* The following code attempts to find the name of the dll by reading the
330 name from the processes memory. Unfortunately it doesn't work right.
331 Doing this the "right way" for Windows is very difficult. FIXME */
332#ifdef DOESNT_WORK
333 memset (&minfo, 0, sizeof minfo);
334 if (VirtualQueryEx (current_process_handle, (LPCVOID) event->lpBaseOfDll,
335 &minfo, sizeof(minfo)) && minfo.BaseAddress) {
336 DWORD len;
337 IMAGE_DOS_HEADER *hmm0 = (IMAGE_DOS_HEADER *) minfo.BaseAddress;
338 HMODULE hmm = (HMODULE) (((DWORD) hmm0) + hmm0->e_lfanew);
339
340 if ((len = GetModuleFileName (hmm, dll_buf, MAX_PATH)))
341 {
342 dll_name = dll_buf;
343 dll_name[len] = '\0';
344 }
345 }
346#endif
24e60978 347
3cee93ac
CF
348 /* Attempt to read the name of the dll that was detected.
349 This is documented to work only when actively debugging
350 a program. It will not work for attached processes. */
351 if (dll_name == NULL || *dll_name == '\0')
24e60978 352 {
3cee93ac 353 int size = event->fUnicode ? sizeof (WCHAR) : sizeof (char);
24e60978
SC
354 int len = 0;
355 char b[2];
3cee93ac
CF
356
357 ReadProcessMemory (current_process_handle,
358 (LPCVOID) event->lpImageName,
359 (char *) &dll_name_ptr,
360 sizeof (dll_name_ptr), &done);
361
362 /* See if we could read the address of a string, and that the
363 address isn't null. */
364
365 if (done != sizeof (dll_name_ptr) || !dll_name_ptr)
366 return 1;
367
24e60978
SC
368 do
369 {
3cee93ac
CF
370 ReadProcessMemory (current_process_handle,
371 (LPCVOID) (dll_name_ptr + len * size),
24e60978
SC
372 &b,
373 size,
374 &done);
375 len++;
376 }
377 while ((b[0] != 0 || b[size - 1] != 0) && done == size);
378
24e60978
SC
379 dll_name = alloca (len);
380
3cee93ac 381 if (event->fUnicode)
24e60978
SC
382 {
383 WCHAR *unicode_dll_name = (WCHAR *) alloca (len * sizeof (WCHAR));
3cee93ac
CF
384 ReadProcessMemory (current_process_handle,
385 (LPCVOID) dll_name_ptr,
24e60978
SC
386 unicode_dll_name,
387 len * sizeof (WCHAR),
388 &done);
389
390 WideCharToMultiByte (CP_ACP, 0,
391 unicode_dll_name, len,
392 dll_name, len, 0, 0);
393 }
394 else
395 {
3cee93ac
CF
396 ReadProcessMemory (current_process_handle,
397 (LPCVOID) dll_name_ptr,
24e60978
SC
398 dll_name,
399 len,
400 &done);
401 }
24e60978 402 }
3cee93ac
CF
403
404 if (!dll_name)
405 return 1;
406
407 while ((p = strchr (dll_name, '\\')))
408 *p = '/';
409
410 /* FIXME!! It would be nice to define one symbol which pointed to the
411 front of the dll if we can't find any symbols. */
412
413 if (!(dll_basename = strrchr(dll_name, '/')))
414 dll_basename = dll_name;
415 else
416 dll_basename++;
417
418 ALL_OBJFILES(objfile)
419 {
420 char *objfile_basename;
421 objfile_basename = strrchr(objfile->name, '/');
422
423 if (objfile_basename &&
424 strcmp(dll_basename, objfile_basename + 1) == 0)
425 {
426 printf_unfiltered ("%x:%s (symbols previously loaded)\n",
427 event->lpBaseOfDll, dll_name);
428 goto out;
429 }
430 }
431
432 /* The symbols in a dll are offset by 0x1000, which is the
433 the offset from 0 of the first byte in an image - because
434 of the file header and the section alignment.
435
436 FIXME: Is this the real reason that we need the 0x1000 ? */
437
438 printf_unfiltered ("%x:%s", event->lpBaseOfDll, dll_name);
65b07ddc 439 symbol_file_add (dll_name, 0, (int) event->lpBaseOfDll + 0x1000, 0, 0, 0, 0, 1);
3cee93ac
CF
440 printf_unfiltered ("\n");
441
442out:
1750a5ef 443 return 1;
24e60978
SC
444}
445
3cee93ac
CF
446/* Handle DEBUG_STRING output from child process.
447 Cygwin prepends its messages with a "cygwin:". Interpret this as
448 a Cygwin signal. Otherwise just print the string as a warning. */
449static int
450handle_output_debug_string (struct target_waitstatus *ourstatus)
451{
452 char *s;
453 int gotasig = FALSE;
454
455 if (!target_read_string
456 ((CORE_ADDR) current_event.u.DebugString.lpDebugStringData, &s, 1024, 0)
457 || !s || !*s)
458 return gotasig;
459
460 if (strncmp(s, CYGWIN_SIGNAL_STRING, sizeof(CYGWIN_SIGNAL_STRING) - 1))
461 {
462 warning (s);
463 }
464 else
465 {
466 char *p;
467 /*last_sig = */strtol(s + sizeof(CYGWIN_SIGNAL_STRING) - 1, &p, 0);
0714f9bf
SS
468 gotasig = target_signal_from_host (last_sig);
469 ourstatus->value.sig = gotasig;
470 if (gotasig)
3cee93ac
CF
471 ourstatus->kind = TARGET_WAITKIND_STOPPED;
472 }
473
474 free (s);
475 return gotasig;
476}
24e60978 477
36339ecd 478static int
3cee93ac 479handle_exception (struct target_waitstatus *ourstatus)
24e60978
SC
480{
481 int i;
482 int done = 0;
3cee93ac
CF
483 thread_info *th;
484
24e60978
SC
485 ourstatus->kind = TARGET_WAITKIND_STOPPED;
486
3cee93ac
CF
487 /* Record the context of the current thread */
488 th = thread_rec (current_event.dwThreadId, -1);
24e60978 489
3cee93ac 490 switch (current_event.u.Exception.ExceptionRecord.ExceptionCode)
24e60978 491 {
1ef980b9
SC
492 case EXCEPTION_ACCESS_VIOLATION:
493 DEBUG_EXCEPT (("gdb: Target exception ACCESS_VIOLATION at 0x%08x\n",
3cee93ac 494 current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1ef980b9
SC
495 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
496 break;
497 case STATUS_STACK_OVERFLOW:
498 DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08x\n",
3cee93ac 499 current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1ef980b9
SC
500 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
501 break;
502 case EXCEPTION_BREAKPOINT:
503 DEBUG_EXCEPT (("gdb: Target exception BREAKPOINT at 0x%08x\n",
3cee93ac 504 current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1ef980b9
SC
505 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
506 break;
507 case DBG_CONTROL_C:
508 DEBUG_EXCEPT (("gdb: Target exception CONTROL_C at 0x%08x\n",
3cee93ac 509 current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1ef980b9 510 ourstatus->value.sig = TARGET_SIGNAL_INT;
3cee93ac
CF
511 /* User typed CTRL-C. Continue with this status */
512 last_sig = SIGINT; /* FIXME - should check pass state */
1ef980b9
SC
513 break;
514 case EXCEPTION_SINGLE_STEP:
515 DEBUG_EXCEPT (("gdb: Target exception SINGLE_STEP at 0x%08x\n",
3cee93ac 516 current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1ef980b9
SC
517 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
518 break;
519 default:
36339ecd 520 /* This may be a structured exception handling exception. In
3cee93ac
CF
521 that case, we want to let the program try to handle it, and
522 only break if we see the exception a second time. */
523 if (current_event.u.Exception.dwFirstChance)
36339ecd
ILT
524 return 0;
525
1ef980b9 526 printf_unfiltered ("gdb: unknown target exception 0x%08x at 0x%08x\n",
3cee93ac
CF
527 current_event.u.Exception.ExceptionRecord.ExceptionCode,
528 current_event.u.Exception.ExceptionRecord.ExceptionAddress);
24e60978 529 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
1ef980b9 530 break;
24e60978 531 }
24e60978 532 exception_count++;
36339ecd 533 return 1;
24e60978
SC
534}
535
3cee93ac
CF
536/* Resume all artificially suspended threads if we are continuing
537 execution */
538static BOOL
539child_continue (DWORD continue_status, int id)
540{
541 int i;
542 thread_info *th;
543 BOOL res;
544
545 DEBUG_EVENTS (("ContinueDebugEvent (cpid=%d, ctid=%d, DBG_CONTINUE);\n",
546 current_event.dwProcessId, current_event.dwThreadId));
0714f9bf
SS
547 res = ContinueDebugEvent (current_event.dwProcessId,
548 current_event.dwThreadId,
549 continue_status);
550 if (res)
3cee93ac
CF
551 for (th = &thread_head; (th = th->next) != NULL; )
552 if (((id == -1) || (id == th->id)) && th->suspend_count)
553 {
554 for (i = 0; i < th->suspend_count; i++)
555 (void) ResumeThread (th->h);
556 th->suspend_count = 0;
557 }
558
559 return res;
560}
561
24e60978
SC
562static int
563child_wait (int pid, struct target_waitstatus *ourstatus)
564{
565 /* We loop when we get a non-standard exception rather than return
566 with a SPURIOUS because resume can try and step or modify things,
3cee93ac 567 which needs a current_thread->h. But some of these exceptions mark
24e60978
SC
568 the birth or death of threads, which mean that the current thread
569 isn't necessarily what you think it is. */
570
571 while (1)
572 {
36339ecd 573 DWORD continue_status;
0714f9bf 574 BOOL debug_event = WaitForDebugEvent (&current_event, 20);
3cee93ac
CF
575 char *p;
576 thread_info *th;
577 int sig;
24e60978 578
0714f9bf 579 if (debug_event)
24e60978 580 {
0714f9bf
SS
581 event_count++;
582
583 continue_status = DBG_CONTINUE;
584
585 switch (current_event.dwDebugEventCode)
586 {
587 case CREATE_THREAD_DEBUG_EVENT:
588 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
589 current_event.dwProcessId, current_event.dwThreadId,
590 "CREATE_THREAD_DEBUG_EVENT"));
591 /* Record the existence of this thread */
592 child_add_thread (current_event.dwThreadId,
593 current_event.u.CreateThread.hThread);
594 if (info_verbose)
595 printf_unfiltered ("[New %s]\n",
596 target_pid_to_str (current_event.dwThreadId));
597 break;
598
599 case EXIT_THREAD_DEBUG_EVENT:
600 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
601 current_event.dwProcessId, current_event.dwThreadId,
602 "EXIT_THREAD_DEBUG_EVENT"));
603 child_delete_thread (current_event.dwThreadId);
604 break;
605
606 case CREATE_PROCESS_DEBUG_EVENT:
607 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
608 current_event.dwProcessId, current_event.dwThreadId,
609 "CREATE_PROCESS_DEBUG_EVENT"));
610 current_process_handle = current_event.u.CreateProcessInfo.hProcess;
611
612 main_thread_id = inferior_pid = current_event.dwThreadId;
613 /* Add the main thread */
614 current_thread = child_add_thread (inferior_pid,
615 current_event.u.CreateProcessInfo.hThread);
616 break;
617
618 case EXIT_PROCESS_DEBUG_EVENT:
619 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
620 current_event.dwProcessId, current_event.dwThreadId,
621 "EXIT_PROCESS_DEBUG_EVENT"));
622 ourstatus->kind = TARGET_WAITKIND_EXITED;
623 ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
624 CloseHandle (current_process_handle);
625 return current_event.dwProcessId;
626 break;
627
628 case LOAD_DLL_DEBUG_EVENT:
629 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
630 current_event.dwProcessId, current_event.dwThreadId,
631 "LOAD_DLL_DEBUG_EVENT"));
632 catch_errors (handle_load_dll, NULL, "", RETURN_MASK_ALL);
633 registers_changed(); /* mark all regs invalid */
634 break;
635
636 case UNLOAD_DLL_DEBUG_EVENT:
637 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
638 current_event.dwProcessId, current_event.dwThreadId,
639 "UNLOAD_DLL_DEBUG_EVENT"));
640 break; /* FIXME: don't know what to do here */
641
642 case EXCEPTION_DEBUG_EVENT:
643 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
644 current_event.dwProcessId, current_event.dwThreadId,
645 "EXCEPTION_DEBUG_EVENT"));
646 if (handle_exception (ourstatus))
647 return current_event.dwThreadId;
648 continue_status = DBG_EXCEPTION_NOT_HANDLED;
649 break;
650
651 case OUTPUT_DEBUG_STRING_EVENT: /* message from the kernel */
652 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
653 current_event.dwProcessId, current_event.dwThreadId,
654 "OUTPUT_DEBUG_STRING_EVENT"));
655 if (handle_output_debug_string (ourstatus))
656 return main_thread_id;
657 break;
658 default:
659 printf_unfiltered ("gdb: kernel event for pid=%d tid=%d\n",
660 current_event.dwProcessId,
661 current_event.dwThreadId);
662 printf_unfiltered (" unknown event code %d\n",
663 current_event.dwDebugEventCode);
664 break;
665 }
666
667 CHECK (child_continue (continue_status, -1));
24e60978 668 }
0714f9bf
SS
669 else
670 {
671 int detach = 0;
3cee93ac 672
0714f9bf
SS
673 if (ui_loop_hook != NULL)
674 detach = ui_loop_hook (0);
675
676 if (detach)
677 child_kill_inferior ();
678 }
24e60978
SC
679 }
680}
681
24e60978
SC
682/* Attach to process PID, then initialize for debugging it. */
683
684static void
685child_attach (args, from_tty)
686 char *args;
687 int from_tty;
688{
689 BOOL ok;
690
691 if (!args)
692 error_no_arg ("process-id to attach");
693
3cee93ac 694 current_event.dwProcessId = strtoul (args, 0, 0);
24e60978 695
3cee93ac 696 ok = DebugActiveProcess (current_event.dwProcessId);
24e60978
SC
697
698 if (!ok)
699 error ("Can't attach to process.");
700
24e60978
SC
701 exception_count = 0;
702 event_count = 0;
703
704 if (from_tty)
705 {
706 char *exec_file = (char *) get_exec_file (0);
707
708 if (exec_file)
709 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
3cee93ac 710 target_pid_to_str (current_event.dwProcessId));
24e60978
SC
711 else
712 printf_unfiltered ("Attaching to %s\n",
3cee93ac 713 target_pid_to_str (current_event.dwProcessId));
24e60978
SC
714
715 gdb_flush (gdb_stdout);
716 }
717
24e60978
SC
718 push_target (&child_ops);
719}
720
24e60978
SC
721static void
722child_detach (args, from_tty)
723 char *args;
724 int from_tty;
725{
726 if (from_tty)
727 {
728 char *exec_file = get_exec_file (0);
729 if (exec_file == 0)
730 exec_file = "";
731 printf_unfiltered ("Detaching from program: %s %s\n", exec_file,
732 target_pid_to_str (inferior_pid));
733 gdb_flush (gdb_stdout);
734 }
735 inferior_pid = 0;
736 unpush_target (&child_ops);
737}
738
24e60978
SC
739/* Print status information about what we're accessing. */
740
741static void
742child_files_info (ignore)
743 struct target_ops *ignore;
744{
745 printf_unfiltered ("\tUsing the running image of %s %s.\n",
746 attach_flag ? "attached" : "child", target_pid_to_str (inferior_pid));
747}
748
749/* ARGSUSED */
750static void
751child_open (arg, from_tty)
752 char *arg;
753 int from_tty;
754{
755 error ("Use the \"run\" command to start a Unix child process.");
756}
757
eb708f2e 758/* Start an inferior win32 child process and sets inferior_pid to its pid.
24e60978
SC
759 EXEC_FILE is the file to run.
760 ALLARGS is a string containing the arguments to the program.
761 ENV is the environment vector to pass. Errors reported with error(). */
762
24e60978
SC
763static void
764child_create_inferior (exec_file, allargs, env)
765 char *exec_file;
766 char *allargs;
767 char **env;
768{
1750a5ef
SC
769 char real_path[MAXPATHLEN];
770 char *winenv;
771 char *temp;
772 int envlen;
773 int i;
774
24e60978
SC
775 STARTUPINFO si;
776 PROCESS_INFORMATION pi;
777 struct target_waitstatus dummy;
778 BOOL ret;
779 DWORD flags;
eb708f2e 780 char *args;
24e60978
SC
781
782 if (!exec_file)
783 {
784 error ("No executable specified, use `target exec'.\n");
785 }
786
787 memset (&si, 0, sizeof (si));
788 si.cb = sizeof (si);
789
1a443730 790 cygwin32_conv_to_win32_path (exec_file, real_path);
24e60978 791
3cee93ac 792 flags = DEBUG_ONLY_THIS_PROCESS;
24e60978
SC
793
794 if (new_group)
795 flags |= CREATE_NEW_PROCESS_GROUP;
796
797 if (new_console)
798 flags |= CREATE_NEW_CONSOLE;
799
3d78f532
SC
800 args = alloca (strlen (real_path) + strlen (allargs) + 2);
801
802 strcpy (args, real_path);
eb708f2e 803
eb708f2e
SC
804 strcat (args, " ");
805 strcat (args, allargs);
806
e88c49c3
DE
807 /* Prepare the environment vars for CreateProcess. */
808 {
809 /* This code use to assume all env vars were file names and would
810 translate them all to win32 style. That obviously doesn't work in the
2dcfc9c7
DE
811 general case. The current rule is that we only translate PATH.
812 We need to handle PATH because we're about to call CreateProcess and
813 it uses PATH to find DLL's. Fortunately PATH has a well-defined value
814 in both posix and win32 environments. cygwin.dll will change it back
815 to posix style if necessary. */
e88c49c3
DE
816
817 static const char *conv_path_names[] =
818 {
819 "PATH=",
820 0
821 };
e88c49c3
DE
822
823 /* CreateProcess takes the environment list as a null terminated set of
824 strings (i.e. two nulls terminate the list). */
825
826 /* Get total size for env strings. */
827 for (envlen = 0, i = 0; env[i] && *env[i]; i++)
828 {
2dcfc9c7 829 int j, len;
e88c49c3 830
2dcfc9c7
DE
831 for (j = 0; conv_path_names[j]; j++)
832 {
833 len = strlen (conv_path_names[j]);
834 if (strncmp (conv_path_names[j], env[i], len) == 0)
e88c49c3 835 {
1a443730 836 if (cygwin32_posix_path_list_p (env[i] + len))
2dcfc9c7 837 envlen += len
1a443730 838 + cygwin32_posix_to_win32_path_list_buf_size (env[i] + len);
2dcfc9c7
DE
839 else
840 envlen += strlen (env[i]) + 1;
841 break;
e88c49c3 842 }
e88c49c3 843 }
2dcfc9c7 844 if (conv_path_names[j] == NULL)
e88c49c3
DE
845 envlen += strlen (env[i]) + 1;
846 }
847
848 winenv = alloca (envlen + 1);
849
850 /* Copy env strings into new buffer. */
3cee93ac 851 for (temp = winenv, i = 0; env[i] && *env[i]; i++)
e88c49c3 852 {
2dcfc9c7 853 int j, len;
e88c49c3 854
2dcfc9c7
DE
855 for (j = 0; conv_path_names[j]; j++)
856 {
857 len = strlen (conv_path_names[j]);
858 if (strncmp (conv_path_names[j], env[i], len) == 0)
e88c49c3 859 {
1a443730 860 if (cygwin32_posix_path_list_p (env[i] + len))
e88c49c3
DE
861 {
862 memcpy (temp, env[i], len);
1a443730 863 cygwin32_posix_to_win32_path_list (env[i] + len, temp + len);
e88c49c3 864 }
2dcfc9c7
DE
865 else
866 strcpy (temp, env[i]);
867 break;
e88c49c3 868 }
e88c49c3 869 }
2dcfc9c7 870 if (conv_path_names[j] == NULL)
e88c49c3 871 strcpy (temp, env[i]);
2dcfc9c7 872
e88c49c3
DE
873 temp += strlen (temp) + 1;
874 }
875
876 /* Final nil string to terminate new env. */
877 *temp = 0;
878 }
1750a5ef 879
1750a5ef 880 ret = CreateProcess (0,
3d78f532 881 args, /* command line */
24e60978
SC
882 NULL, /* Security */
883 NULL, /* thread */
884 TRUE, /* inherit handles */
885 flags, /* start flags */
1750a5ef 886 winenv,
24e60978
SC
887 NULL, /* current directory */
888 &si,
889 &pi);
890 if (!ret)
686941a9 891 error ("Error creating process %s, (error %d)\n", exec_file, GetLastError());
24e60978
SC
892
893 exception_count = 0;
894 event_count = 0;
895
3cee93ac
CF
896 current_process_handle = pi.hProcess;
897 current_event.dwProcessId = pi.dwProcessId;
898 memset (&current_event, 0, sizeof (current_event));
899 inferior_pid = current_event.dwThreadId = pi.dwThreadId;
24e60978 900 push_target (&child_ops);
3cee93ac 901 child_init_thread_list ();
24e60978
SC
902 init_wait_for_inferior ();
903 clear_proceed_status ();
904 target_terminal_init ();
905 target_terminal_inferior ();
906
907 /* Ignore the first trap */
908 child_wait (inferior_pid, &dummy);
909
910 proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
911}
912
913static void
914child_mourn_inferior ()
915{
3cee93ac 916 (void) child_continue (DBG_CONTINUE, -1);
24e60978
SC
917 unpush_target (&child_ops);
918 generic_mourn_inferior ();
919}
920
24e60978
SC
921/* Send a SIGINT to the process group. This acts just like the user typed a
922 ^C on the controlling terminal. */
923
b607efe7 924static void
24e60978
SC
925child_stop ()
926{
1ef980b9 927 DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
24e60978 928 CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0));
1ef980b9 929 registers_changed(); /* refresh register state */
24e60978
SC
930}
931
932int
eb708f2e
SC
933child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
934 int write, struct target_ops *target)
24e60978
SC
935{
936 DWORD done;
937 if (write)
938 {
1ef980b9
SC
939 DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08x\n",
940 len, memaddr));
3cee93ac
CF
941 WriteProcessMemory (current_process_handle, (LPVOID) memaddr, our,
942 len, &done);
943 FlushInstructionCache (current_process_handle, (LPCVOID) memaddr, len);
24e60978
SC
944 }
945 else
946 {
1ef980b9
SC
947 DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08x\n",
948 len, memaddr));
3cee93ac
CF
949 ReadProcessMemory (current_process_handle, (LPCVOID) memaddr, our, len,
950 &done);
24e60978
SC
951 }
952 return done;
953}
954
955void
956child_kill_inferior (void)
957{
3cee93ac
CF
958 CHECK (TerminateProcess (current_process_handle, 0));
959
b5edcb45
ILT
960 for (;;)
961 {
3cee93ac 962 if (!child_continue (DBG_CONTINUE, -1))
b5edcb45 963 break;
3cee93ac 964 if (!WaitForDebugEvent (&current_event, INFINITE))
b5edcb45 965 break;
3cee93ac 966 if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
b5edcb45
ILT
967 break;
968 }
969
3cee93ac
CF
970 CHECK (CloseHandle (current_process_handle));
971
972 /* this may fail in an attached process so don't check. */
973 (void) CloseHandle (current_thread->h);
1ef980b9 974 target_mourn_inferior(); /* or just child_mourn_inferior? */
24e60978
SC
975}
976
977void
3cee93ac 978child_resume (int pid, int step, enum target_signal sig)
24e60978 979{
3cee93ac
CF
980 int i;
981 thread_info *th;
982 DWORD continue_status = last_sig > 0 && last_sig < NSIG ?
983 DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE;
24e60978 984
3cee93ac
CF
985 DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, sig=%d);\n",
986 pid, step, sig));
987
988 /* Get context for currently selected thread */
989 th = thread_rec (current_event.dwThreadId, FALSE);
24e60978
SC
990 if (step)
991 {
1ef980b9 992#ifdef i386
24e60978
SC
993 /* Single step by setting t bit */
994 child_fetch_inferior_registers (PS_REGNUM);
3cee93ac 995 th->context.EFlags |= FLAG_TRACE_BIT;
454ffae5 996#endif
24e60978
SC
997 }
998
3cee93ac 999 if (th->context.ContextFlags)
24e60978 1000 {
3cee93ac
CF
1001 CHECK (SetThreadContext (th->h, &th->context));
1002 th->context.ContextFlags = 0;
24e60978
SC
1003 }
1004
3cee93ac
CF
1005 /* Allow continuing with the same signal that interrupted us.
1006 Otherwise complain. */
1007 if (sig && sig != last_sig)
1008 fprintf_unfiltered (gdb_stderr, "Can't send signals to the child. signal %d\n", sig);
24e60978 1009
3cee93ac
CF
1010 last_sig = 0;
1011 child_continue (continue_status, pid);
24e60978
SC
1012}
1013
1014static void
1015child_prepare_to_store ()
1016{
1017 /* Do nothing, since we can store individual regs */
1018}
1019
1020static int
1021child_can_run ()
1022{
1023 return 1;
1024}
1025
1026static void
1027child_close ()
1028{
1ef980b9 1029 DEBUG_EVENTS (("gdb: child_close, inferior_pid=%d\n", inferior_pid));
24e60978 1030}
1ef980b9 1031
c719b714
JM
1032struct target_ops child_ops ;
1033
ba4d67c2
FN
1034static void
1035init_child_ops(void)
24e60978 1036{
3cee93ac 1037 child_ops.to_shortname = "child";
c719b714 1038 child_ops.to_longname = "Win32 child process";
3cee93ac
CF
1039 child_ops.to_doc = "Win32 child process (started by the \"run\" command).";
1040 child_ops.to_open = child_open;
1041 child_ops.to_close = child_close;
1042 child_ops.to_attach = child_attach;
1043 child_ops.to_detach = child_detach;
1044 child_ops.to_resume = child_resume;
1045 child_ops.to_wait = child_wait;
c719b714
JM
1046 child_ops.to_fetch_registers = child_fetch_inferior_registers;
1047 child_ops.to_store_registers = child_store_inferior_registers;
3cee93ac
CF
1048 child_ops.to_prepare_to_store = child_prepare_to_store;
1049 child_ops.to_xfer_memory = child_xfer_memory;
1050 child_ops.to_files_info = child_files_info;
c719b714
JM
1051 child_ops.to_insert_breakpoint = memory_insert_breakpoint;
1052 child_ops.to_remove_breakpoint = memory_remove_breakpoint;
1053 child_ops.to_terminal_init = terminal_init_inferior;
3cee93ac 1054 child_ops.to_terminal_inferior = terminal_inferior;
c719b714 1055 child_ops.to_terminal_ours_for_output = terminal_ours_for_output;
3cee93ac
CF
1056 child_ops.to_terminal_ours = terminal_ours;
1057 child_ops.to_terminal_info = child_terminal_info;
1058 child_ops.to_kill = child_kill_inferior;
1059 child_ops.to_load = 0;
1060 child_ops.to_lookup_symbol = 0;
c719b714 1061 child_ops.to_create_inferior = child_create_inferior;
3cee93ac
CF
1062 child_ops.to_mourn_inferior = child_mourn_inferior;
1063 child_ops.to_can_run = child_can_run;
1064 child_ops.to_notice_signals = 0;
bc8bd256 1065 child_ops.to_thread_alive = win32_child_thread_alive;
3cee93ac 1066 child_ops.to_stop = child_stop;
c719b714 1067 child_ops.to_stratum = process_stratum;
3cee93ac
CF
1068 child_ops.DONT_USE = 0;
1069 child_ops.to_has_all_memory = 1;
1070 child_ops.to_has_memory = 1;
1071 child_ops.to_has_stack = 1;
1072 child_ops.to_has_registers = 1;
1073 child_ops.to_has_execution = 1;
1074 child_ops.to_sections = 0;
1075 child_ops.to_sections_end = 0;
c719b714
JM
1076 child_ops.to_magic = OPS_MAGIC;
1077}
24e60978
SC
1078
1079void
1080_initialize_inftarg ()
1081{
1ef980b9 1082 struct cmd_list_element *c;
c719b714 1083 init_child_ops() ;
1ef980b9 1084
24e60978
SC
1085 add_show_from_set
1086 (add_set_cmd ("new-console", class_support, var_boolean,
1087 (char *) &new_console,
1088 "Set creation of new console when creating child process.",
1089 &setlist),
1090 &showlist);
1091
1092 add_show_from_set
1093 (add_set_cmd ("new-group", class_support, var_boolean,
1094 (char *) &new_group,
1095 "Set creation of new group when creating child process.",
1096 &setlist),
1097 &showlist);
1098
1ef980b9
SC
1099 add_show_from_set
1100 (add_set_cmd ("debugexec", class_support, var_boolean,
1101 (char *) &debug_exec,
1102 "Set whether to display execution in child process.",
1103 &setlist),
1104 &showlist);
1105
1106 add_show_from_set
1107 (add_set_cmd ("debugevents", class_support, var_boolean,
1108 (char *) &debug_events,
1109 "Set whether to display kernel events in child process.",
1110 &setlist),
1111 &showlist);
1112
1113 add_show_from_set
1114 (add_set_cmd ("debugmemory", class_support, var_boolean,
1115 (char *) &debug_memory,
1116 "Set whether to display memory accesses in child process.",
1117 &setlist),
1118 &showlist);
1119
1120 add_show_from_set
1121 (add_set_cmd ("debugexceptions", class_support, var_boolean,
1122 (char *) &debug_exceptions,
1123 "Set whether to display kernel exceptions in child process.",
1124 &setlist),
1125 &showlist);
1126
24e60978
SC
1127 add_target (&child_ops);
1128}
3cee93ac
CF
1129
1130/* Determine if the thread referenced by "pid" is alive
1131 by "polling" it. If WaitForSingleObject returns WAIT_OBJECT_0
1132 it means that the pid has died. Otherwise it is assumed to be alive. */
1133static int
bc8bd256 1134win32_child_thread_alive (int pid)
3cee93ac
CF
1135{
1136 return WaitForSingleObject(thread_rec (pid, FALSE)->h, 0) == WAIT_OBJECT_0 ?
1137 FALSE : TRUE;
1138}
1139
1140/* Convert pid to printable format. */
1141char *
1142cygwin_pid_to_str (int pid)
1143{
1144 static char buf[80];
1145 if (pid == current_event.dwProcessId)
1146 sprintf (buf, "process %d", pid);
1147 else
1148 sprintf (buf, "thread %d.0x%x", current_event.dwProcessId, pid);
1149 return buf;
1150}