]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/windows-nat.c
Protoization.
[thirdparty/binutils-gdb.git] / gdb / windows-nat.c
1 /* Target-vector operations for controlling win32 child processes, for GDB.
2 Copyright 1995, 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
3 Contributed by Cygnus Solutions, A Red Hat Company.
4
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
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
21 */
22
23 /* by Steve Chamberlain, sac@cygnus.com */
24
25 /* We assume we're being built with and will be used for cygwin. */
26
27 #include "defs.h"
28 #include "frame.h" /* required by inferior.h */
29 #include "inferior.h"
30 #include "target.h"
31 #include "gdbcore.h"
32 #include "command.h"
33 #include <signal.h>
34 #include <sys/types.h>
35 #include <fcntl.h>
36 #include <stdlib.h>
37 #include <windows.h>
38 #include <imagehlp.h>
39 #include <sys/cygwin.h>
40
41 #include "buildsym.h"
42 #include "symfile.h"
43 #include "objfiles.h"
44 #include "gdb_string.h"
45 #include "gdbthread.h"
46 #include "gdbcmd.h"
47 #include <sys/param.h>
48 #include <unistd.h>
49
50 /* The ui's event loop. */
51 extern int (*ui_loop_hook) (int signo);
52
53 /* If we're not using the old Cygwin header file set, define the
54 following which never should have been in the generic Win32 API
55 headers in the first place since they were our own invention... */
56 #ifndef _GNU_H_WINDOWS_H
57 #define FLAG_TRACE_BIT 0x100
58 #define CONTEXT_DEBUGGER (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
59 #endif
60
61 /* The string sent by cygwin when it processes a signal.
62 FIXME: This should be in a cygwin include file. */
63 #define CYGWIN_SIGNAL_STRING "cygwin: signal"
64
65 #define CHECK(x) check (x, __FILE__,__LINE__)
66 #define DEBUG_EXEC(x) if (debug_exec) printf x
67 #define DEBUG_EVENTS(x) if (debug_events) printf x
68 #define DEBUG_MEM(x) if (debug_memory) printf x
69 #define DEBUG_EXCEPT(x) if (debug_exceptions) printf x
70
71 /* Forward declaration */
72 extern struct target_ops child_ops;
73
74 static void child_stop (void);
75 static int win32_child_thread_alive (int);
76 void child_kill_inferior (void);
77
78 static int last_sig = 0; /* Set if a signal was received from the
79 debugged process */
80 /* Thread information structure used to track information that is
81 not available in gdb's thread structure. */
82 typedef struct thread_info_struct
83 {
84 struct thread_info_struct *next;
85 DWORD id;
86 HANDLE h;
87 char *name;
88 int suspend_count;
89 CONTEXT context;
90 STACKFRAME sf;
91 } thread_info;
92
93 static thread_info thread_head;
94
95 /* The process and thread handles for the above context. */
96
97 static DEBUG_EVENT current_event; /* The current debug event from
98 WaitForDebugEvent */
99 static HANDLE current_process_handle; /* Currently executing process */
100 static thread_info *current_thread; /* Info on currently selected thread */
101 static DWORD main_thread_id; /* Thread ID of the main thread */
102
103 /* Counts of things. */
104 static int exception_count = 0;
105 static int event_count = 0;
106
107 /* User options. */
108 static int new_console = 0;
109 static int new_group = 1;
110 static int debug_exec = 0; /* show execution */
111 static int debug_events = 0; /* show events from kernel */
112 static int debug_memory = 0; /* show target memory accesses */
113 static int debug_exceptions = 0; /* show target exceptions */
114
115 /* This vector maps GDB's idea of a register's number into an address
116 in the win32 exception context vector.
117
118 It also contains the bit mask needed to load the register in question.
119
120 One day we could read a reg, we could inspect the context we
121 already have loaded, if it doesn't have the bit set that we need,
122 we read that set of registers in using GetThreadContext. If the
123 context already contains what we need, we just unpack it. Then to
124 write a register, first we have to ensure that the context contains
125 the other regs of the group, and then we copy the info in and set
126 out bit. */
127
128 #define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
129 static const int mappings[] =
130 {
131 context_offset (Eax),
132 context_offset (Ecx),
133 context_offset (Edx),
134 context_offset (Ebx),
135 context_offset (Esp),
136 context_offset (Ebp),
137 context_offset (Esi),
138 context_offset (Edi),
139 context_offset (Eip),
140 context_offset (EFlags),
141 context_offset (SegCs),
142 context_offset (SegSs),
143 context_offset (SegDs),
144 context_offset (SegEs),
145 context_offset (SegFs),
146 context_offset (SegGs),
147 context_offset (FloatSave.RegisterArea[0 * 10]),
148 context_offset (FloatSave.RegisterArea[1 * 10]),
149 context_offset (FloatSave.RegisterArea[2 * 10]),
150 context_offset (FloatSave.RegisterArea[3 * 10]),
151 context_offset (FloatSave.RegisterArea[4 * 10]),
152 context_offset (FloatSave.RegisterArea[5 * 10]),
153 context_offset (FloatSave.RegisterArea[6 * 10]),
154 context_offset (FloatSave.RegisterArea[7 * 10]),
155 context_offset (FloatSave.ControlWord),
156 context_offset (FloatSave.StatusWord),
157 context_offset (FloatSave.TagWord),
158 context_offset (FloatSave.ErrorSelector),
159 context_offset (FloatSave.ErrorOffset),
160 context_offset (FloatSave.DataSelector),
161 context_offset (FloatSave.DataOffset),
162 context_offset (FloatSave.ErrorSelector)
163 };
164
165 #undef context_offset
166
167 /* This vector maps the target's idea of an exception (extracted
168 from the DEBUG_EVENT structure) to GDB's idea. */
169
170 struct xlate_exception
171 {
172 int them;
173 enum target_signal us;
174 };
175
176 static const struct xlate_exception
177 xlate[] =
178 {
179 {EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV},
180 {STATUS_STACK_OVERFLOW, TARGET_SIGNAL_SEGV},
181 {EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP},
182 {DBG_CONTROL_C, TARGET_SIGNAL_INT},
183 {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP},
184 {-1, -1}};
185
186 /* Find a thread record given a thread id.
187 If get_context then also retrieve the context for this
188 thread. */
189 static thread_info *
190 thread_rec (DWORD id, int get_context)
191 {
192 thread_info *th;
193
194 for (th = &thread_head; (th = th->next) != NULL;)
195 if (th->id == id)
196 {
197 if (!th->suspend_count && get_context)
198 {
199 if (get_context > 0 && id != current_event.dwThreadId)
200 th->suspend_count = SuspendThread (th->h) + 1;
201 else if (get_context < 0)
202 th->suspend_count = -1;
203
204 th->context.ContextFlags = CONTEXT_DEBUGGER;
205 GetThreadContext (th->h, &th->context);
206 }
207 return th;
208 }
209
210 return NULL;
211 }
212
213 /* Add a thread to the thread list */
214 static thread_info *
215 child_add_thread (DWORD id, HANDLE h)
216 {
217 thread_info *th;
218
219 if ((th = thread_rec (id, FALSE)))
220 return th;
221
222 th = (thread_info *) xmalloc (sizeof (*th));
223 memset (th, 0, sizeof (*th));
224 th->id = id;
225 th->h = h;
226 th->next = thread_head.next;
227 thread_head.next = th;
228 add_thread (id);
229 return th;
230 }
231
232 /* Clear out any old thread list and reintialize it to a
233 pristine state. */
234 static void
235 child_init_thread_list (void)
236 {
237 thread_info *th = &thread_head;
238
239 DEBUG_EVENTS (("gdb: child_init_thread_list\n"));
240 init_thread_list ();
241 while (th->next != NULL)
242 {
243 thread_info *here = th->next;
244 th->next = here->next;
245 (void) CloseHandle (here->h);
246 free (here);
247 }
248 }
249
250 /* Delete a thread from the list of threads */
251 static void
252 child_delete_thread (DWORD id)
253 {
254 thread_info *th;
255
256 if (info_verbose)
257 printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (id));
258 delete_thread (id);
259
260 for (th = &thread_head;
261 th->next != NULL && th->next->id != id;
262 th = th->next)
263 continue;
264
265 if (th->next != NULL)
266 {
267 thread_info *here = th->next;
268 th->next = here->next;
269 CloseHandle (here->h);
270 free (here);
271 }
272 }
273
274 static void
275 check (BOOL ok, const char *file, int line)
276 {
277 if (!ok)
278 printf_filtered ("error return %s:%d was %lu\n", file, line, GetLastError ());
279 }
280
281 static void
282 do_child_fetch_inferior_registers (int r)
283 {
284 char *context_offset = ((char *) &current_thread->context) + mappings[r];
285 long l;
286 if (r == FCS_REGNUM)
287 {
288 l = *((long *)context_offset) & 0xffff;
289 supply_register (r, (char *) &l);
290 }
291 else if (r == FOP_REGNUM)
292 {
293 l = (*((long *)context_offset) >> 16) & ((1 << 11) - 1);
294 supply_register (r, (char *) &l);
295 }
296 else if (r >= 0)
297 supply_register (r, context_offset);
298 else
299 {
300 for (r = 0; r < NUM_REGS; r++)
301 do_child_fetch_inferior_registers (r);
302 }
303 }
304
305 static void
306 child_fetch_inferior_registers (int r)
307 {
308 current_thread = thread_rec (inferior_pid, TRUE);
309 do_child_fetch_inferior_registers (r);
310 }
311
312 static void
313 do_child_store_inferior_registers (int r)
314 {
315 if (r >= 0)
316 read_register_gen (r, ((char *) &current_thread->context) + mappings[r]);
317 else
318 {
319 for (r = 0; r < NUM_REGS; r++)
320 do_child_store_inferior_registers (r);
321 }
322 }
323
324 /* Store a new register value into the current thread context */
325 static void
326 child_store_inferior_registers (int r)
327 {
328 current_thread = thread_rec (inferior_pid, TRUE);
329 do_child_store_inferior_registers (r);
330 }
331
332 #include <psapi.h>
333 static int psapi_loaded = 0;
334 static HMODULE psapi_module_handle = NULL;
335 static BOOL WINAPI (*psapi_EnumProcessModules)(HANDLE, HMODULE*, DWORD, LPDWORD)= NULL;
336 static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO, DWORD)= NULL;
337 static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD)= NULL;
338
339 int psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
340 {
341 DWORD len;
342 MODULEINFO mi;
343 int i;
344 HMODULE dh_buf [ 1 ];
345 HMODULE* DllHandle = dh_buf;
346 DWORD cbNeeded;
347 BOOL ok;
348
349 if (!psapi_loaded ||
350 psapi_EnumProcessModules == NULL ||
351 psapi_GetModuleInformation == NULL ||
352 psapi_GetModuleFileNameExA == NULL)
353 {
354 if (psapi_loaded)goto failed;
355 psapi_loaded = 1;
356 psapi_module_handle = LoadLibrary ("psapi.dll");
357 if (!psapi_module_handle)
358 {
359 /* printf_unfiltered ("error loading psapi.dll: %u", GetLastError ());*/
360 goto failed;
361 }
362 psapi_EnumProcessModules = GetProcAddress (psapi_module_handle, "EnumProcessModules" );
363 psapi_GetModuleInformation = GetProcAddress (psapi_module_handle, "GetModuleInformation");
364 psapi_GetModuleFileNameExA = (void *) GetProcAddress (psapi_module_handle,
365 "GetModuleFileNameExA");
366 if (psapi_EnumProcessModules == NULL ||
367 psapi_GetModuleInformation == NULL ||
368 psapi_GetModuleFileNameExA == NULL)
369 goto failed;
370 }
371
372 cbNeeded = 0;
373 ok = (*psapi_EnumProcessModules) (current_process_handle,
374 DllHandle,
375 sizeof (HMODULE),
376 &cbNeeded);
377
378 if (!ok || !cbNeeded)
379 goto failed;
380
381 DllHandle = (HMODULE*) alloca (cbNeeded);
382 if (!DllHandle)
383 goto failed;
384
385 ok = (*psapi_EnumProcessModules) (current_process_handle,
386 DllHandle,
387 cbNeeded,
388 &cbNeeded);
389 if (!ok)
390 goto failed;
391
392 for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
393 {
394 if (!(*psapi_GetModuleInformation) (current_process_handle,
395 DllHandle [i],
396 &mi,
397 sizeof (mi)))
398 error ("Can't get module info");
399
400 len = (*psapi_GetModuleFileNameExA) (current_process_handle,
401 DllHandle [i],
402 dll_name_ret,
403 MAX_PATH);
404 if (len == 0)
405 error ("Error getting dll name: %u\n", GetLastError ());
406
407 if ((DWORD) (mi.lpBaseOfDll) == BaseAddress)
408 return 1;
409 }
410
411 failed:
412 dll_name_ret[0] = '\0';
413 return 0;
414 }
415
416 /* Encapsulate the information required in a call to
417 symbol_file_add_args */
418 struct safe_symbol_file_add_args
419 {
420 char *name;
421 int from_tty;
422 struct section_addr_info *addrs;
423 int mainline;
424 int flags;
425 struct ui_file *err, *out;
426 struct objfile *ret;
427 };
428
429 /* Call symbol_file_add with stderr redirected. We don't care if there
430 are errors. */
431 static int
432 safe_symbol_file_add_stub (void *argv)
433 {
434 #define p ((struct safe_symbol_file_add_args *)argv)
435 p->ret = symbol_file_add (p->name, p->from_tty, p->addrs, p->mainline, p->flags);
436 return !!p->ret;
437 #undef p
438 }
439
440 /* Restore gdb's stderr after calling symbol_file_add */
441 static void
442 safe_symbol_file_add_cleanup (void *p)
443 {
444 #define sp ((struct safe_symbol_file_add_args *)p)
445 gdb_flush (gdb_stderr);
446 gdb_flush (gdb_stdout);
447 ui_file_delete (gdb_stderr);
448 ui_file_delete (gdb_stdout);
449 gdb_stderr = sp->err;
450 gdb_stdout = sp->err;
451 }
452
453 /* symbol_file_add wrapper that prevents errors from being displayed. */
454 static struct objfile *
455 safe_symbol_file_add (char *name, int from_tty,
456 struct section_addr_info *addrs,
457 int mainline, int flags)
458
459 {
460 struct safe_symbol_file_add_args p;
461 struct cleanup *cleanup;
462
463 cleanup = make_cleanup (safe_symbol_file_add_cleanup, &p);
464
465 p.err = gdb_stderr;
466 p.out = gdb_stdout;
467 gdb_flush (gdb_stderr);
468 gdb_flush (gdb_stdout);
469 gdb_stderr = ui_file_new ();
470 gdb_stdout = ui_file_new ();
471 p.name = name;
472 p.from_tty = from_tty;
473 p.addrs = addrs;
474 p.mainline = mainline;
475 p.flags = flags;
476 catch_errors (safe_symbol_file_add_stub, &p, "", RETURN_MASK_ERROR);
477
478 do_cleanups (cleanup);
479 return p.ret;
480 }
481
482 /* Maintain a linked list of "so" information. */
483 struct so_stuff
484 {
485 struct so_stuff *next, **last;
486 DWORD load_addr;
487 char name[0];
488 } solib_start, *solib_end;
489
490 /* Remember the maximum DLL length for printing in info dll command. */
491 int max_dll_name_len;
492
493 /* Wait for child to do something. Return pid of child, or -1 in case
494 of error; store status through argument pointer OURSTATUS. */
495 static int
496 handle_load_dll (PTR dummy ATTRIBUTE_UNUSED)
497 {
498 LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
499 DWORD dll_name_ptr;
500 DWORD done;
501 char dll_buf[MAX_PATH + 1];
502 struct so_stuff *so, *solast;
503 char *dll_name = NULL;
504 DWORD dll_base = 0;
505 int len;
506 char *p;
507
508 dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
509
510 if (!psapi_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf))
511 dll_buf[0] = dll_buf[sizeof(dll_buf) - 1] = '\0';
512
513 dll_name = dll_buf;
514
515 /* Attempt to read the name of the dll that was detected.
516 This is documented to work only when actively debugging
517 a program. It will not work for attached processes. */
518 if (dll_name == NULL || *dll_name == '\0')
519 {
520 DWORD size = event->fUnicode ? sizeof (WCHAR) : sizeof (char);
521 int len = 0;
522 char b[2];
523
524 ReadProcessMemory (current_process_handle,
525 (LPCVOID) event->lpImageName,
526 (char *) &dll_name_ptr,
527 sizeof (dll_name_ptr), &done);
528
529 /* See if we could read the address of a string, and that the
530 address isn't null. */
531
532 if (done != sizeof (dll_name_ptr) || !dll_name_ptr)
533 return 1;
534
535 do
536 {
537 ReadProcessMemory (current_process_handle,
538 (LPCVOID) (dll_name_ptr + len * size),
539 &b,
540 size,
541 &done);
542 len++;
543 }
544 while ((b[0] != 0 || b[size - 1] != 0) && done == size);
545
546 dll_name = alloca (len);
547
548 if (event->fUnicode)
549 {
550 WCHAR *unicode_dll_name = (WCHAR *) alloca (len * sizeof (WCHAR));
551 ReadProcessMemory (current_process_handle,
552 (LPCVOID) dll_name_ptr,
553 unicode_dll_name,
554 len * sizeof (WCHAR),
555 &done);
556
557 WideCharToMultiByte (CP_ACP, 0,
558 unicode_dll_name, len,
559 dll_name, len, 0, 0);
560 }
561 else
562 {
563 ReadProcessMemory (current_process_handle,
564 (LPCVOID) dll_name_ptr,
565 dll_name,
566 len,
567 &done);
568 }
569 }
570
571 if (!dll_name)
572 return 1;
573
574 (void) strlwr (dll_name);
575
576 while ((p = strchr (dll_name, '\\')))
577 *p = '/';
578
579 so = (struct so_stuff *) xmalloc (sizeof (struct so_stuff) + strlen (dll_name) + 8 + 2);
580 so->load_addr = (DWORD) event->lpBaseOfDll + 0x1000;
581 strcpy (so->name, dll_name);
582
583 solib_end->next = so;
584 solib_end = so;
585 so->next = NULL;
586
587 len = strlen (dll_name);
588 if (len > max_dll_name_len)
589 max_dll_name_len = len;
590
591 return 1;
592 }
593
594 /* Return name of last loaded DLL. */
595 char *
596 child_solib_loaded_library_pathname (int pid)
597 {
598 return !solib_end || !solib_end->name[0]? NULL : solib_end->name;
599 }
600
601 /* Clear list of loaded DLLs. */
602 void
603 child_clear_solibs (void)
604 {
605 struct so_stuff *so, *so1 = solib_start.next;
606
607 while ((so = so1) != NULL)
608 {
609 so1 = so->next;
610 free (so);
611 }
612
613 solib_start.next = NULL;
614 solib_end = &solib_start;
615 max_dll_name_len = sizeof ("DLL Name") - 1;
616 }
617
618 /* Add DLL symbol information. */
619 void
620 child_solib_add (char *filename, int from_tty, struct target_ops *t)
621 {
622 struct section_addr_info section_addrs;
623
624 /* The symbols in a dll are offset by 0x1000, which is the
625 the offset from 0 of the first byte in an image - because
626 of the file header and the section alignment. */
627
628 if (!solib_end || !solib_end->name[0])
629 return;
630
631 memset (&section_addrs, 0, sizeof (section_addrs));
632 section_addrs.other[0].name = ".text";
633 section_addrs.other[0].addr = solib_end->load_addr;
634 safe_symbol_file_add (solib_end->name, 0, &section_addrs, 0, OBJF_SHARED);
635
636 return;
637 }
638
639 /* Load DLL symbol info. */
640 void
641 dll_symbol_command (char *args, int from_tty)
642 {
643 struct section_addr_info section_addrs;
644
645 dont_repeat ();
646
647 if (args == NULL)
648 error ("dll-symbols requires a file name");
649
650 safe_symbol_file_add (args, 0, NULL, 0, OBJF_SHARED);
651 }
652
653 /* List currently loaded DLLs. */
654 void
655 info_dll_command (char *ignore, int from_tty)
656 {
657 struct so_stuff *so = &solib_start;
658
659 if (!so->next)
660 return;
661
662 printf ("%*s Load Address\n", -max_dll_name_len, "DLL Name");
663 while ((so = so->next) != NULL)
664 printf_filtered ("%*s %08lx\n", -max_dll_name_len, so->name, so->load_addr);
665
666 return;
667 }
668
669 /* Handle DEBUG_STRING output from child process.
670 Cygwin prepends its messages with a "cygwin:". Interpret this as
671 a Cygwin signal. Otherwise just print the string as a warning. */
672 static int
673 handle_output_debug_string (struct target_waitstatus *ourstatus)
674 {
675 char *s;
676 int gotasig = FALSE;
677
678 if (!target_read_string
679 ((CORE_ADDR) current_event.u.DebugString.lpDebugStringData, &s, 1024, 0)
680 || !s || !*s)
681 return gotasig;
682
683 if (strncmp (s, CYGWIN_SIGNAL_STRING, sizeof (CYGWIN_SIGNAL_STRING) - 1) != 0)
684 {
685 if (strncmp (s, "cYg", 3) != 0)
686 warning ("%s", s);
687 }
688 else
689 {
690 char *p;
691 int sig = strtol (s + sizeof (CYGWIN_SIGNAL_STRING) - 1, &p, 0);
692 gotasig = target_signal_from_host (sig);
693 ourstatus->value.sig = gotasig;
694 if (gotasig)
695 ourstatus->kind = TARGET_WAITKIND_STOPPED;
696 }
697
698 free (s);
699 return gotasig;
700 }
701
702 static int
703 handle_exception (struct target_waitstatus *ourstatus)
704 {
705 thread_info *th;
706 DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode;
707
708 ourstatus->kind = TARGET_WAITKIND_STOPPED;
709
710 /* Record the context of the current thread */
711 th = thread_rec (current_event.dwThreadId, -1);
712
713 last_sig = 0;
714
715 switch (code)
716 {
717 case EXCEPTION_ACCESS_VIOLATION:
718 DEBUG_EXCEPT (("gdb: Target exception ACCESS_VIOLATION at 0x%08lx\n",
719 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
720 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
721 last_sig = SIGSEGV;
722 break;
723 case STATUS_FLOAT_UNDERFLOW:
724 case STATUS_FLOAT_DIVIDE_BY_ZERO:
725 case STATUS_FLOAT_OVERFLOW:
726 case STATUS_INTEGER_DIVIDE_BY_ZERO:
727 DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08lx\n",
728 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
729 ourstatus->value.sig = TARGET_SIGNAL_FPE;
730 last_sig = SIGFPE;
731 break;
732 case STATUS_STACK_OVERFLOW:
733 DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08lx\n",
734 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
735 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
736 break;
737 case EXCEPTION_BREAKPOINT:
738 DEBUG_EXCEPT (("gdb: Target exception BREAKPOINT at 0x%08lx\n",
739 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
740 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
741 break;
742 case DBG_CONTROL_C:
743 DEBUG_EXCEPT (("gdb: Target exception CONTROL_C at 0x%08lx\n",
744 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
745 ourstatus->value.sig = TARGET_SIGNAL_INT;
746 last_sig = SIGINT; /* FIXME - should check pass state */
747 break;
748 case EXCEPTION_SINGLE_STEP:
749 DEBUG_EXCEPT (("gdb: Target exception SINGLE_STEP at 0x%08lx\n",
750 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
751 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
752 break;
753 case EXCEPTION_ILLEGAL_INSTRUCTION:
754 DEBUG_EXCEPT (("gdb: Target exception SINGLE_ILL at 0x%08lx\n",
755 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
756 ourstatus->value.sig = TARGET_SIGNAL_ILL;
757 last_sig = SIGILL;
758 break;
759 default:
760 printf_unfiltered ("gdb: unknown target exception 0x%08lx at 0x%08lx\n",
761 current_event.u.Exception.ExceptionRecord.ExceptionCode,
762 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress);
763 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
764 break;
765 }
766 exception_count++;
767 return 1;
768 }
769
770 /* Resume all artificially suspended threads if we are continuing
771 execution */
772 static BOOL
773 child_continue (DWORD continue_status, int id)
774 {
775 int i;
776 thread_info *th;
777 BOOL res;
778
779 DEBUG_EVENTS (("ContinueDebugEvent (cpid=%ld, ctid=%ld, DBG_CONTINUE);\n",
780 current_event.dwProcessId, current_event.dwThreadId));
781 res = ContinueDebugEvent (current_event.dwProcessId,
782 current_event.dwThreadId,
783 continue_status);
784 continue_status = 0;
785 if (res)
786 for (th = &thread_head; (th = th->next) != NULL;)
787 if (((id == -1) || (id == (int) th->id)) && th->suspend_count)
788 {
789 for (i = 0; i < th->suspend_count; i++)
790 (void) ResumeThread (th->h);
791 th->suspend_count = 0;
792 }
793
794 return res;
795 }
796
797 /* Get the next event from the child. Return 1 if the event requires
798 handling by WFI (or whatever).
799 */
800 static int
801 get_child_debug_event (int pid ATTRIBUTE_UNUSED, struct target_waitstatus *ourstatus)
802 {
803 int breakout = 0;
804 BOOL debug_event;
805 DWORD continue_status, event_code;
806 thread_info *th = NULL;
807 static thread_info dummy_thread_info;
808 int retval = 0;
809
810 if (!(debug_event = WaitForDebugEvent (&current_event, 1000)))
811 goto out;
812
813 event_count++;
814 continue_status = DBG_CONTINUE;
815
816 event_code = current_event.dwDebugEventCode;
817 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
818
819 switch (event_code)
820 {
821 case CREATE_THREAD_DEBUG_EVENT:
822 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
823 (unsigned) current_event.dwProcessId,
824 (unsigned) current_event.dwThreadId,
825 "CREATE_THREAD_DEBUG_EVENT"));
826 /* Record the existence of this thread */
827 th = child_add_thread (current_event.dwThreadId,
828 current_event.u.CreateThread.hThread);
829 if (info_verbose)
830 printf_unfiltered ("[New %s]\n",
831 target_pid_to_str (current_event.dwThreadId));
832 retval = current_event.dwThreadId;
833 break;
834
835 case EXIT_THREAD_DEBUG_EVENT:
836 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
837 (unsigned) current_event.dwProcessId,
838 (unsigned) current_event.dwThreadId,
839 "EXIT_THREAD_DEBUG_EVENT"));
840 child_delete_thread (current_event.dwThreadId);
841 th = &dummy_thread_info;
842 break;
843
844 case CREATE_PROCESS_DEBUG_EVENT:
845 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
846 (unsigned) current_event.dwProcessId,
847 (unsigned) current_event.dwThreadId,
848 "CREATE_PROCESS_DEBUG_EVENT"));
849 current_process_handle = current_event.u.CreateProcessInfo.hProcess;
850
851 main_thread_id = inferior_pid = current_event.dwThreadId;
852 /* Add the main thread */
853 th = child_add_thread (current_event.dwProcessId,
854 current_event.u.CreateProcessInfo.hProcess);
855 th = child_add_thread (inferior_pid,
856 current_event.u.CreateProcessInfo.hThread);
857 retval = ourstatus->value.related_pid = current_event.dwProcessId;
858 break;
859
860 case EXIT_PROCESS_DEBUG_EVENT:
861 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
862 (unsigned) current_event.dwProcessId,
863 (unsigned) current_event.dwThreadId,
864 "EXIT_PROCESS_DEBUG_EVENT"));
865 ourstatus->kind = TARGET_WAITKIND_EXITED;
866 ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
867 CloseHandle (current_process_handle);
868 retval = current_event.dwProcessId;
869 break;
870
871 case LOAD_DLL_DEBUG_EVENT:
872 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
873 (unsigned) current_event.dwProcessId,
874 (unsigned) current_event.dwThreadId,
875 "LOAD_DLL_DEBUG_EVENT"));
876 catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL);
877 registers_changed (); /* mark all regs invalid */
878 ourstatus->kind = TARGET_WAITKIND_LOADED;
879 ourstatus->value.integer = 0;
880 retval = current_event.dwProcessId;
881 break;
882
883 case UNLOAD_DLL_DEBUG_EVENT:
884 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
885 (unsigned) current_event.dwProcessId,
886 (unsigned) current_event.dwThreadId,
887 "UNLOAD_DLL_DEBUG_EVENT"));
888 break; /* FIXME: don't know what to do here */
889
890 case EXCEPTION_DEBUG_EVENT:
891 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
892 (unsigned) current_event.dwProcessId,
893 (unsigned) current_event.dwThreadId,
894 "EXCEPTION_DEBUG_EVENT"));
895 handle_exception (ourstatus);
896 retval = current_event.dwThreadId;
897 break;
898
899 case OUTPUT_DEBUG_STRING_EVENT: /* message from the kernel */
900 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
901 (unsigned) current_event.dwProcessId,
902 (unsigned) current_event.dwThreadId,
903 "OUTPUT_DEBUG_STRING_EVENT"));
904 if (handle_output_debug_string ( ourstatus))
905 retval = current_event.dwProcessId;
906 break;
907 default:
908 printf_unfiltered ("gdb: kernel event for pid=%ld tid=%ld\n",
909 (DWORD) current_event.dwProcessId,
910 (DWORD) current_event.dwThreadId);
911 printf_unfiltered (" unknown event code %ld\n",
912 current_event.dwDebugEventCode);
913 break;
914 }
915
916 if (!retval)
917 CHECK (child_continue (continue_status, -1));
918 else
919 current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
920
921 out:
922 return retval;
923 }
924
925 /* Wait for interesting events to occur in the target process. */
926 static int
927 child_wait (int pid, struct target_waitstatus *ourstatus)
928 {
929 /* We loop when we get a non-standard exception rather than return
930 with a SPURIOUS because resume can try and step or modify things,
931 which needs a current_thread->h. But some of these exceptions mark
932 the birth or death of threads, which mean that the current thread
933 isn't necessarily what you think it is. */
934
935 while (1)
936 {
937 int retval = get_child_debug_event (pid, ourstatus);
938 if (retval)
939 return retval;
940 else
941 {
942 int detach = 0;
943
944 if (ui_loop_hook != NULL)
945 detach = ui_loop_hook (0);
946
947 if (detach)
948 child_kill_inferior ();
949 }
950 }
951 }
952
953 /* Attach to process PID, then initialize for debugging it. */
954
955 static void
956 child_attach (char *args, int from_tty)
957 {
958 BOOL ok;
959
960 if (!args)
961 error_no_arg ("process-id to attach");
962
963 current_event.dwProcessId = strtoul (args, 0, 0);
964
965 ok = DebugActiveProcess (current_event.dwProcessId);
966
967 if (!ok)
968 error ("Can't attach to process.");
969
970 exception_count = 0;
971 event_count = 0;
972
973 child_init_thread_list ();
974 child_clear_solibs ();
975
976 if (from_tty)
977 {
978 char *exec_file = (char *) get_exec_file (0);
979
980 if (exec_file)
981 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
982 target_pid_to_str (current_event.dwProcessId));
983 else
984 printf_unfiltered ("Attaching to %s\n",
985 target_pid_to_str (current_event.dwProcessId));
986
987 gdb_flush (gdb_stdout);
988 }
989
990 push_target (&child_ops);
991 }
992
993 static void
994 child_detach (char *args ATTRIBUTE_UNUSED, int from_tty)
995 {
996 if (from_tty)
997 {
998 char *exec_file = get_exec_file (0);
999 if (exec_file == 0)
1000 exec_file = "";
1001 printf_unfiltered ("Detaching from program: %s %s\n", exec_file,
1002 target_pid_to_str (inferior_pid));
1003 gdb_flush (gdb_stdout);
1004 }
1005 inferior_pid = 0;
1006 unpush_target (&child_ops);
1007 }
1008
1009 /* Print status information about what we're accessing. */
1010
1011 static void
1012 child_files_info (struct target_ops *ignore ATTRIBUTE_UNUSED)
1013 {
1014 printf_unfiltered ("\tUsing the running image of %s %s.\n",
1015 attach_flag ? "attached" : "child", target_pid_to_str (inferior_pid));
1016 }
1017
1018 /* ARGSUSED */
1019 static void
1020 child_open (char *arg ATTRIBUTE_UNUSED, int from_tty ATTRIBUTE_UNUSED)
1021 {
1022 error ("Use the \"run\" command to start a Unix child process.");
1023 }
1024
1025 /* Start an inferior win32 child process and sets inferior_pid to its pid.
1026 EXEC_FILE is the file to run.
1027 ALLARGS is a string containing the arguments to the program.
1028 ENV is the environment vector to pass. Errors reported with error(). */
1029
1030 static void
1031 child_create_inferior (char *exec_file, char *allargs, char **env)
1032 {
1033 char real_path[MAXPATHLEN];
1034 char *winenv;
1035 char *temp;
1036 int envlen;
1037 int i;
1038 STARTUPINFO si;
1039 PROCESS_INFORMATION pi;
1040 struct target_waitstatus dummy;
1041 BOOL ret;
1042 DWORD flags;
1043 char *args;
1044 extern int stop_after_trap;
1045
1046 if (!exec_file)
1047 error ("No executable specified, use `target exec'.\n");
1048
1049 memset (&si, 0, sizeof (si));
1050 si.cb = sizeof (si);
1051
1052 cygwin_conv_to_win32_path (exec_file, real_path);
1053
1054 flags = DEBUG_ONLY_THIS_PROCESS;
1055
1056 if (new_group)
1057 flags |= CREATE_NEW_PROCESS_GROUP;
1058
1059 if (new_console)
1060 flags |= CREATE_NEW_CONSOLE;
1061
1062 args = alloca (strlen (real_path) + strlen (allargs) + 2);
1063
1064 strcpy (args, real_path);
1065
1066 strcat (args, " ");
1067 strcat (args, allargs);
1068
1069 /* Prepare the environment vars for CreateProcess. */
1070 {
1071 /* This code use to assume all env vars were file names and would
1072 translate them all to win32 style. That obviously doesn't work in the
1073 general case. The current rule is that we only translate PATH.
1074 We need to handle PATH because we're about to call CreateProcess and
1075 it uses PATH to find DLL's. Fortunately PATH has a well-defined value
1076 in both posix and win32 environments. cygwin.dll will change it back
1077 to posix style if necessary. */
1078
1079 static const char *conv_path_names[] =
1080 {
1081 "PATH=",
1082 0
1083 };
1084
1085 /* CreateProcess takes the environment list as a null terminated set of
1086 strings (i.e. two nulls terminate the list). */
1087
1088 /* Get total size for env strings. */
1089 for (envlen = 0, i = 0; env[i] && *env[i]; i++)
1090 {
1091 int j, len;
1092
1093 for (j = 0; conv_path_names[j]; j++)
1094 {
1095 len = strlen (conv_path_names[j]);
1096 if (strncmp (conv_path_names[j], env[i], len) == 0)
1097 {
1098 if (cygwin_posix_path_list_p (env[i] + len))
1099 envlen += len
1100 + cygwin_posix_to_win32_path_list_buf_size (env[i] + len);
1101 else
1102 envlen += strlen (env[i]) + 1;
1103 break;
1104 }
1105 }
1106 if (conv_path_names[j] == NULL)
1107 envlen += strlen (env[i]) + 1;
1108 }
1109
1110 winenv = alloca (envlen + 1);
1111
1112 /* Copy env strings into new buffer. */
1113 for (temp = winenv, i = 0; env[i] && *env[i]; i++)
1114 {
1115 int j, len;
1116
1117 for (j = 0; conv_path_names[j]; j++)
1118 {
1119 len = strlen (conv_path_names[j]);
1120 if (strncmp (conv_path_names[j], env[i], len) == 0)
1121 {
1122 if (cygwin_posix_path_list_p (env[i] + len))
1123 {
1124 memcpy (temp, env[i], len);
1125 cygwin_posix_to_win32_path_list (env[i] + len, temp + len);
1126 }
1127 else
1128 strcpy (temp, env[i]);
1129 break;
1130 }
1131 }
1132 if (conv_path_names[j] == NULL)
1133 strcpy (temp, env[i]);
1134
1135 temp += strlen (temp) + 1;
1136 }
1137
1138 /* Final nil string to terminate new env. */
1139 *temp = 0;
1140 }
1141
1142 ret = CreateProcess (0,
1143 args, /* command line */
1144 NULL, /* Security */
1145 NULL, /* thread */
1146 TRUE, /* inherit handles */
1147 flags, /* start flags */
1148 winenv,
1149 NULL, /* current directory */
1150 &si,
1151 &pi);
1152 if (!ret)
1153 error ("Error creating process %s, (error %d)\n", exec_file, GetLastError ());
1154
1155 exception_count = 0;
1156 event_count = 0;
1157
1158 current_process_handle = pi.hProcess;
1159 current_event.dwProcessId = pi.dwProcessId;
1160 memset (&current_event, 0, sizeof (current_event));
1161 inferior_pid = current_event.dwThreadId = pi.dwThreadId;
1162 push_target (&child_ops);
1163 child_init_thread_list ();
1164 child_clear_solibs ();
1165 clear_proceed_status ();
1166 init_wait_for_inferior ();
1167 target_terminal_init ();
1168 target_terminal_inferior ();
1169 last_sig = 0;
1170
1171 while (1)
1172 {
1173 stop_after_trap = 1;
1174 wait_for_inferior ();
1175 if (stop_signal != TARGET_SIGNAL_TRAP)
1176 resume (0, stop_signal);
1177 else
1178 break;
1179 }
1180 stop_after_trap = 0;
1181
1182 /* child_continue (DBG_CONTINUE, -1);*/
1183 proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
1184 }
1185
1186 static void
1187 child_mourn_inferior (void)
1188 {
1189 (void) child_continue (DBG_CONTINUE, -1);
1190 unpush_target (&child_ops);
1191 generic_mourn_inferior ();
1192 }
1193
1194 /* Send a SIGINT to the process group. This acts just like the user typed a
1195 ^C on the controlling terminal. */
1196
1197 static void
1198 child_stop (void)
1199 {
1200 DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
1201 CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
1202 registers_changed (); /* refresh register state */
1203 }
1204
1205 int
1206 child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
1207 int write, struct target_ops *target ATTRIBUTE_UNUSED)
1208 {
1209 DWORD done;
1210 if (write)
1211 {
1212 DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08lx\n",
1213 len, (DWORD) memaddr));
1214 WriteProcessMemory (current_process_handle, (LPVOID) memaddr, our,
1215 len, &done);
1216 FlushInstructionCache (current_process_handle, (LPCVOID) memaddr, len);
1217 }
1218 else
1219 {
1220 DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08lx\n",
1221 len, (DWORD) memaddr));
1222 ReadProcessMemory (current_process_handle, (LPCVOID) memaddr, our, len,
1223 &done);
1224 }
1225 return done;
1226 }
1227
1228 void
1229 child_kill_inferior (void)
1230 {
1231 CHECK (TerminateProcess (current_process_handle, 0));
1232
1233 for (;;)
1234 {
1235 if (!child_continue (DBG_CONTINUE, -1))
1236 break;
1237 if (!WaitForDebugEvent (&current_event, INFINITE))
1238 break;
1239 if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
1240 break;
1241 }
1242
1243 CHECK (CloseHandle (current_process_handle));
1244
1245 /* this may fail in an attached process so don't check. */
1246 (void) CloseHandle (current_thread->h);
1247 target_mourn_inferior (); /* or just child_mourn_inferior? */
1248 }
1249
1250 void
1251 child_resume (int pid, int step, enum target_signal sig)
1252 {
1253 thread_info *th;
1254 DWORD continue_status = last_sig > 0 && last_sig < NSIG ?
1255 DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE;
1256
1257 last_sig = 0;
1258
1259 DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, sig=%d);\n",
1260 pid, step, sig));
1261
1262 /* Get context for currently selected thread */
1263 th = thread_rec (current_event.dwThreadId, FALSE);
1264 if (th)
1265 {
1266 if (step)
1267 {
1268 /* Single step by setting t bit */
1269 child_fetch_inferior_registers (PS_REGNUM);
1270 th->context.EFlags |= FLAG_TRACE_BIT;
1271 }
1272
1273 if (th->context.ContextFlags)
1274 {
1275 CHECK (SetThreadContext (th->h, &th->context));
1276 th->context.ContextFlags = 0;
1277 }
1278 }
1279
1280 /* Allow continuing with the same signal that interrupted us.
1281 Otherwise complain. */
1282
1283 child_continue (continue_status, pid);
1284 }
1285
1286 static void
1287 child_prepare_to_store (void)
1288 {
1289 /* Do nothing, since we can store individual regs */
1290 }
1291
1292 static int
1293 child_can_run (void)
1294 {
1295 return 1;
1296 }
1297
1298 static void
1299 child_close (void)
1300 {
1301 DEBUG_EVENTS (("gdb: child_close, inferior_pid=%d\n", inferior_pid));
1302 }
1303
1304 struct target_ops child_ops;
1305
1306 static void
1307 init_child_ops (void)
1308 {
1309 child_ops.to_shortname = "child";
1310 child_ops.to_longname = "Win32 child process";
1311 child_ops.to_doc = "Win32 child process (started by the \"run\" command).";
1312 child_ops.to_open = child_open;
1313 child_ops.to_close = child_close;
1314 child_ops.to_attach = child_attach;
1315 child_ops.to_detach = child_detach;
1316 child_ops.to_resume = child_resume;
1317 child_ops.to_wait = child_wait;
1318 child_ops.to_fetch_registers = child_fetch_inferior_registers;
1319 child_ops.to_store_registers = child_store_inferior_registers;
1320 child_ops.to_prepare_to_store = child_prepare_to_store;
1321 child_ops.to_xfer_memory = child_xfer_memory;
1322 child_ops.to_files_info = child_files_info;
1323 child_ops.to_insert_breakpoint = memory_insert_breakpoint;
1324 child_ops.to_remove_breakpoint = memory_remove_breakpoint;
1325 child_ops.to_terminal_init = terminal_init_inferior;
1326 child_ops.to_terminal_inferior = terminal_inferior;
1327 child_ops.to_terminal_ours_for_output = terminal_ours_for_output;
1328 child_ops.to_terminal_ours = terminal_ours;
1329 child_ops.to_terminal_info = child_terminal_info;
1330 child_ops.to_kill = child_kill_inferior;
1331 child_ops.to_load = 0;
1332 child_ops.to_lookup_symbol = 0;
1333 child_ops.to_create_inferior = child_create_inferior;
1334 child_ops.to_mourn_inferior = child_mourn_inferior;
1335 child_ops.to_can_run = child_can_run;
1336 child_ops.to_notice_signals = 0;
1337 child_ops.to_thread_alive = win32_child_thread_alive;
1338 child_ops.to_pid_to_str = cygwin_pid_to_str;
1339 child_ops.to_stop = child_stop;
1340 child_ops.to_stratum = process_stratum;
1341 child_ops.DONT_USE = 0;
1342 child_ops.to_has_all_memory = 1;
1343 child_ops.to_has_memory = 1;
1344 child_ops.to_has_stack = 1;
1345 child_ops.to_has_registers = 1;
1346 child_ops.to_has_execution = 1;
1347 child_ops.to_sections = 0;
1348 child_ops.to_sections_end = 0;
1349 child_ops.to_magic = OPS_MAGIC;
1350 }
1351
1352 void
1353 _initialize_inftarg (void)
1354 {
1355 init_child_ops ();
1356
1357 add_com ("dll-symbols", class_files, dll_symbol_command,
1358 "Load dll library symbols from FILE.");
1359
1360 add_com_alias ("sharedlibrary", "dll-symbols", class_alias, 1);
1361
1362 add_show_from_set (add_set_cmd ("new-console", class_support, var_boolean,
1363 (char *) &new_console,
1364 "Set creation of new console when creating child process.",
1365 &setlist),
1366 &showlist);
1367
1368 add_show_from_set (add_set_cmd ("new-group", class_support, var_boolean,
1369 (char *) &new_group,
1370 "Set creation of new group when creating child process.",
1371 &setlist),
1372 &showlist);
1373
1374 add_show_from_set (add_set_cmd ("debugexec", class_support, var_boolean,
1375 (char *) &debug_exec,
1376 "Set whether to display execution in child process.",
1377 &setlist),
1378 &showlist);
1379
1380 add_show_from_set (add_set_cmd ("debugevents", class_support, var_boolean,
1381 (char *) &debug_events,
1382 "Set whether to display kernel events in child process.",
1383 &setlist),
1384 &showlist);
1385
1386 add_show_from_set (add_set_cmd ("debugmemory", class_support, var_boolean,
1387 (char *) &debug_memory,
1388 "Set whether to display memory accesses in child process.",
1389 &setlist),
1390 &showlist);
1391
1392 add_show_from_set (add_set_cmd ("debugexceptions", class_support, var_boolean,
1393 (char *) &debug_exceptions,
1394 "Set whether to display kernel exceptions in child process.",
1395 &setlist),
1396 &showlist);
1397
1398 add_info ("dll", info_dll_command, "Status of loaded DLLs.");
1399 add_info_alias ("sharedlibrary", "dll", 1);
1400
1401 add_target (&child_ops);
1402 }
1403
1404 /* Determine if the thread referenced by "pid" is alive
1405 by "polling" it. If WaitForSingleObject returns WAIT_OBJECT_0
1406 it means that the pid has died. Otherwise it is assumed to be alive. */
1407 static int
1408 win32_child_thread_alive (int pid)
1409 {
1410 return WaitForSingleObject (thread_rec (pid, FALSE)->h, 0) == WAIT_OBJECT_0 ?
1411 FALSE : TRUE;
1412 }
1413
1414 /* Convert pid to printable format. */
1415 char *
1416 cygwin_pid_to_str (int pid)
1417 {
1418 static char buf[80];
1419 if ((DWORD) pid == current_event.dwProcessId)
1420 sprintf (buf, "process %d", pid);
1421 else
1422 sprintf (buf, "thread %ld.0x%x", current_event.dwProcessId, pid);
1423 return buf;
1424 }