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