Tidy up formatting.
[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 36#include <stdlib.h>
cad9cd60 37#include <windows.h>
1e37c281 38#include <imagehlp.h>
29fe111d 39#include <sys/cygwin.h>
cad9cd60 40
24e60978 41#include "buildsym.h"
1ef980b9
SC
42#include "symfile.h"
43#include "objfiles.h"
24e60978 44#include "gdb_string.h"
fdfa3315 45#include "gdbthread.h"
24e60978 46#include "gdbcmd.h"
1750a5ef 47#include <sys/param.h>
1e37c281 48#include <unistd.h>
24e60978 49
0714f9bf 50/* The ui's event loop. */
507f3c78 51extern int (*ui_loop_hook) (int signo);
0714f9bf
SS
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
3cee93ac
CF
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
29fe111d 65#define CHECK(x) check (x, __FILE__,__LINE__)
1ef980b9
SC
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
24e60978
SC
70
71/* Forward declaration */
72extern struct target_ops child_ops;
73
a14ed312
KB
74static void child_stop (void);
75static int win32_child_thread_alive (int);
76void child_kill_inferior (void);
3cee93ac 77
8a892701
CF
78static int last_sig = 0; /* Set if a signal was received from the
79 debugged process */
3cee93ac
CF
80/* Thread information structure used to track information that is
81 not available in gdb's thread structure. */
82typedef struct thread_info_struct
3a4b77d8
JM
83 {
84 struct thread_info_struct *next;
85 DWORD id;
86 HANDLE h;
87 char *name;
88 int suspend_count;
89 CONTEXT context;
1e37c281
JM
90 STACKFRAME sf;
91 } thread_info;
92
29fe111d 93static thread_info thread_head;
24e60978 94
24e60978
SC
95/* The process and thread handles for the above context. */
96
3cee93ac
CF
97static DEBUG_EVENT current_event; /* The current debug event from
98 WaitForDebugEvent */
99static HANDLE current_process_handle; /* Currently executing process */
100static thread_info *current_thread; /* Info on currently selected thread */
3a4b77d8 101static DWORD main_thread_id; /* Thread ID of the main thread */
24e60978
SC
102
103/* Counts of things. */
104static int exception_count = 0;
105static int event_count = 0;
106
107/* User options. */
108static int new_console = 0;
1e37c281 109static int new_group = 1;
3a4b77d8
JM
110static int debug_exec = 0; /* show execution */
111static int debug_events = 0; /* show events from kernel */
112static int debug_memory = 0; /* show target memory accesses */
1ef980b9 113static int debug_exceptions = 0; /* show target exceptions */
24e60978
SC
114
115/* This vector maps GDB's idea of a register's number into an address
3cee93ac 116 in the win32 exception context vector.
24e60978 117
3cee93ac 118 It also contains the bit mask needed to load the register in question.
24e60978
SC
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
3cee93ac
CF
128#define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
129static const int mappings[] =
24e60978 130{
3a4b77d8
JM
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]),
1e37c281
JM
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),
d3a09475 162 context_offset (FloatSave.ErrorSelector)
24e60978
SC
163};
164
d3a09475
JM
165#undef context_offset
166
24e60978
SC
167/* This vector maps the target's idea of an exception (extracted
168 from the DEBUG_EVENT structure) to GDB's idea. */
169
170struct xlate_exception
171 {
172 int them;
173 enum target_signal us;
174 };
175
24e60978
SC
176static const struct xlate_exception
177 xlate[] =
178{
179 {EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV},
9cbf6c0e 180 {STATUS_STACK_OVERFLOW, TARGET_SIGNAL_SEGV},
24e60978
SC
181 {EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP},
182 {DBG_CONTROL_C, TARGET_SIGNAL_INT},
183 {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP},
184 {-1, -1}};
185
3cee93ac
CF
186/* Find a thread record given a thread id.
187 If get_context then also retrieve the context for this
188 thread. */
189static thread_info *
190thread_rec (DWORD id, int get_context)
24e60978 191{
3cee93ac
CF
192 thread_info *th;
193
3a4b77d8 194 for (th = &thread_head; (th = th->next) != NULL;)
3cee93ac
CF
195 if (th->id == id)
196 {
197 if (!th->suspend_count && get_context)
198 {
8a892701 199 if (get_context > 0 && id != current_event.dwThreadId)
3cee93ac
CF
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 */
214static thread_info *
3a4b77d8 215child_add_thread (DWORD id, HANDLE h)
3cee93ac
CF
216{
217 thread_info *th;
218
219 if ((th = thread_rec (id, FALSE)))
220 return th;
221
222 th = (thread_info *) xmalloc (sizeof (*th));
3a4b77d8 223 memset (th, 0, sizeof (*th));
3cee93ac
CF
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;
24e60978
SC
230}
231
3cee93ac
CF
232/* Clear out any old thread list and reintialize it to a
233 pristine state. */
24e60978 234static void
3cee93ac 235child_init_thread_list ()
24e60978 236{
3cee93ac
CF
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)
24e60978 242 {
3cee93ac
CF
243 thread_info *here = th->next;
244 th->next = here->next;
245 (void) CloseHandle (here->h);
246 free (here);
24e60978 247 }
3cee93ac
CF
248}
249
250/* Delete a thread from the list of threads */
251static void
252child_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)
24e60978 266 {
3cee93ac
CF
267 thread_info *here = th->next;
268 th->next = here->next;
269 CloseHandle (here->h);
270 free (here);
24e60978
SC
271 }
272}
273
274static void
3cee93ac
CF
275check (BOOL ok, const char *file, int line)
276{
277 if (!ok)
29fe111d 278 printf_filtered ("error return %s:%d was %lu\n", file, line, GetLastError ());
3cee93ac
CF
279}
280
281static void
282do_child_fetch_inferior_registers (int r)
24e60978 283{
1e37c281
JM
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)
d3a09475 297 supply_register (r, context_offset);
3cee93ac 298 else
24e60978
SC
299 {
300 for (r = 0; r < NUM_REGS; r++)
3cee93ac 301 do_child_fetch_inferior_registers (r);
24e60978 302 }
3cee93ac
CF
303}
304
305static void
306child_fetch_inferior_registers (int r)
307{
308 current_thread = thread_rec (inferior_pid, TRUE);
309 do_child_fetch_inferior_registers (r);
310}
311
312static void
313do_child_store_inferior_registers (int r)
314{
315 if (r >= 0)
316 read_register_gen (r, ((char *) &current_thread->context) + mappings[r]);
24e60978
SC
317 else
318 {
3cee93ac
CF
319 for (r = 0; r < NUM_REGS; r++)
320 do_child_store_inferior_registers (r);
24e60978
SC
321 }
322}
323
3cee93ac
CF
324/* Store a new register value into the current thread context */
325static void
326child_store_inferior_registers (int r)
327{
328 current_thread = thread_rec (inferior_pid, TRUE);
329 do_child_store_inferior_registers (r);
330}
24e60978 331
1e37c281
JM
332#include <psapi.h>
333static int psapi_loaded = 0;
334static HMODULE psapi_module_handle = NULL;
335static BOOL WINAPI (*psapi_EnumProcessModules)(HANDLE, HMODULE*, DWORD, LPDWORD)= NULL;
336static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO, DWORD)= NULL;
337static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD)= NULL;
338
339int 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
29fe111d 392 for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
1e37c281
JM
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)
29fe111d 405 error ("Error getting dll name: %u\n", GetLastError ());
1e37c281
JM
406
407 if ((DWORD) (mi.lpBaseOfDll) == BaseAddress)
408 return 1;
409 }
410
411failed:
412 dll_name_ret[0] = '\0';
413 return 0;
414}
415
450005e7
CF
416/* Encapsulate the information required in a call to
417 symbol_file_add_args */
8a892701
CF
418struct 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;
7c5c87c0 425 struct ui_file *err, *out;
8a892701
CF
426 struct objfile *ret;
427};
428
450005e7
CF
429/* Call symbol_file_add with stderr redirected. We don't care if there
430 are errors. */
8a892701
CF
431static int
432safe_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
450005e7 440/* Restore gdb's stderr after calling symbol_file_add */
8a892701 441static void
7c5c87c0 442safe_symbol_file_add_cleanup (void *p)
8a892701 443{
7c5c87c0 444#define sp ((struct safe_symbol_file_add_args *)p)
450005e7 445 gdb_flush (gdb_stderr);
7c5c87c0 446 gdb_flush (gdb_stdout);
8a892701 447 ui_file_delete (gdb_stderr);
7c5c87c0
CF
448 ui_file_delete (gdb_stdout);
449 gdb_stderr = sp->err;
450 gdb_stdout = sp->err;
8a892701
CF
451}
452
450005e7 453/* symbol_file_add wrapper that prevents errors from being displayed. */
8a892701
CF
454static struct objfile *
455safe_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
7c5c87c0 463 cleanup = make_cleanup (safe_symbol_file_add_cleanup, &p);
8a892701 464
7c5c87c0
CF
465 p.err = gdb_stderr;
466 p.out = gdb_stdout;
450005e7 467 gdb_flush (gdb_stderr);
7c5c87c0 468 gdb_flush (gdb_stdout);
8a892701 469 gdb_stderr = ui_file_new ();
7c5c87c0 470 gdb_stdout = ui_file_new ();
8a892701
CF
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
450005e7
CF
482/* Maintain a linked list of "so" information. */
483struct 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. */
491int max_dll_name_len;
492
24e60978
SC
493/* Wait for child to do something. Return pid of child, or -1 in case
494 of error; store status through argument pointer OURSTATUS. */
1750a5ef 495static int
29fe111d 496handle_load_dll (PTR dummy ATTRIBUTE_UNUSED)
24e60978 497{
3a4b77d8 498 LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
24e60978
SC
499 DWORD dll_name_ptr;
500 DWORD done;
3cee93ac 501 char dll_buf[MAX_PATH + 1];
450005e7
CF
502 struct so_stuff *so, *solast;
503 char *dll_name = NULL;
504 DWORD dll_base = 0;
505 int len;
506 char *p;
3cee93ac 507
3a4b77d8 508 dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
3cee93ac 509
1e37c281
JM
510 if (!psapi_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf))
511 dll_buf[0] = dll_buf[sizeof(dll_buf) - 1] = '\0';
3cee93ac 512
1e37c281 513 dll_name = dll_buf;
24e60978 514
3cee93ac
CF
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')
24e60978 519 {
29fe111d 520 DWORD size = event->fUnicode ? sizeof (WCHAR) : sizeof (char);
24e60978
SC
521 int len = 0;
522 char b[2];
3cee93ac
CF
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
3a4b77d8 530 address isn't null. */
3cee93ac
CF
531
532 if (done != sizeof (dll_name_ptr) || !dll_name_ptr)
533 return 1;
534
24e60978
SC
535 do
536 {
3cee93ac
CF
537 ReadProcessMemory (current_process_handle,
538 (LPCVOID) (dll_name_ptr + len * size),
24e60978
SC
539 &b,
540 size,
541 &done);
542 len++;
543 }
544 while ((b[0] != 0 || b[size - 1] != 0) && done == size);
545
24e60978
SC
546 dll_name = alloca (len);
547
3cee93ac 548 if (event->fUnicode)
24e60978
SC
549 {
550 WCHAR *unicode_dll_name = (WCHAR *) alloca (len * sizeof (WCHAR));
3cee93ac
CF
551 ReadProcessMemory (current_process_handle,
552 (LPCVOID) dll_name_ptr,
24e60978
SC
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 {
3cee93ac
CF
563 ReadProcessMemory (current_process_handle,
564 (LPCVOID) dll_name_ptr,
24e60978
SC
565 dll_name,
566 len,
567 &done);
568 }
24e60978 569 }
3cee93ac
CF
570
571 if (!dll_name)
572 return 1;
573
29fe111d
CF
574 (void) strlwr (dll_name);
575
3cee93ac
CF
576 while ((p = strchr (dll_name, '\\')))
577 *p = '/';
578
450005e7
CF
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. */
595char *
596child_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. */
602void
603child_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. */
619void
620child_solib_add (char *filename, int from_tty, struct target_ops *t)
621{
622 struct section_addr_info section_addrs;
623
3cee93ac
CF
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
8a892701 626 of the file header and the section alignment. */
3cee93ac 627
450005e7
CF
628 if (!solib_end || !solib_end->name[0])
629 return;
630
631 memset (&section_addrs, 0, sizeof (section_addrs));
0aa9cf96 632 section_addrs.other[0].name = ".text";
450005e7
CF
633 section_addrs.other[0].addr = solib_end->load_addr;
634 safe_symbol_file_add (solib_end->name, 0, &section_addrs, 0, OBJF_SHARED);
3cee93ac 635
450005e7
CF
636 return;
637}
638
639/* Load DLL symbol info. */
640void
641dll_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. */
654void
655info_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)
7c5c87c0 664 printf_filtered ("%*s %08lx\n", -max_dll_name_len, so->name, so->load_addr);
450005e7
CF
665
666 return;
24e60978
SC
667}
668
3cee93ac
CF
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. */
672static int
673handle_output_debug_string (struct target_waitstatus *ourstatus)
674{
675 char *s;
676 int gotasig = FALSE;
677
678 if (!target_read_string
3a4b77d8 679 ((CORE_ADDR) current_event.u.DebugString.lpDebugStringData, &s, 1024, 0)
3cee93ac
CF
680 || !s || !*s)
681 return gotasig;
682
d3a09475 683 if (strncmp (s, CYGWIN_SIGNAL_STRING, sizeof (CYGWIN_SIGNAL_STRING) - 1) != 0)
3cee93ac 684 {
d3a09475 685 if (strncmp (s, "cYg", 3) != 0)
29fe111d 686 warning ("%s", s);
3cee93ac 687 }
d3a09475 688 else
3cee93ac
CF
689 {
690 char *p;
1e37c281
JM
691 int sig = strtol (s + sizeof (CYGWIN_SIGNAL_STRING) - 1, &p, 0);
692 gotasig = target_signal_from_host (sig);
0714f9bf
SS
693 ourstatus->value.sig = gotasig;
694 if (gotasig)
3cee93ac
CF
695 ourstatus->kind = TARGET_WAITKIND_STOPPED;
696 }
697
698 free (s);
699 return gotasig;
700}
24e60978 701
36339ecd 702static int
450005e7 703handle_exception (struct target_waitstatus *ourstatus)
24e60978 704{
3cee93ac 705 thread_info *th;
29fe111d 706 DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode;
3cee93ac 707
29fe111d 708 ourstatus->kind = TARGET_WAITKIND_STOPPED;
8a892701 709
3cee93ac
CF
710 /* Record the context of the current thread */
711 th = thread_rec (current_event.dwThreadId, -1);
24e60978 712
8a892701
CF
713 last_sig = 0;
714
29fe111d 715 switch (code)
24e60978 716 {
1ef980b9 717 case EXCEPTION_ACCESS_VIOLATION:
29fe111d
CF
718 DEBUG_EXCEPT (("gdb: Target exception ACCESS_VIOLATION at 0x%08lx\n",
719 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1ef980b9 720 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
8a892701 721 last_sig = SIGSEGV;
1ef980b9 722 break;
3b7c8b74
JM
723 case STATUS_FLOAT_UNDERFLOW:
724 case STATUS_FLOAT_DIVIDE_BY_ZERO:
725 case STATUS_FLOAT_OVERFLOW:
726 case STATUS_INTEGER_DIVIDE_BY_ZERO:
29fe111d
CF
727 DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08lx\n",
728 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
3b7c8b74 729 ourstatus->value.sig = TARGET_SIGNAL_FPE;
29fe111d 730 last_sig = SIGFPE;
3b7c8b74 731 break;
1ef980b9 732 case STATUS_STACK_OVERFLOW:
29fe111d
CF
733 DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08lx\n",
734 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1ef980b9
SC
735 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
736 break;
737 case EXCEPTION_BREAKPOINT:
29fe111d
CF
738 DEBUG_EXCEPT (("gdb: Target exception BREAKPOINT at 0x%08lx\n",
739 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1ef980b9
SC
740 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
741 break;
742 case DBG_CONTROL_C:
29fe111d
CF
743 DEBUG_EXCEPT (("gdb: Target exception CONTROL_C at 0x%08lx\n",
744 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1ef980b9 745 ourstatus->value.sig = TARGET_SIGNAL_INT;
8a892701 746 last_sig = SIGINT; /* FIXME - should check pass state */
1ef980b9
SC
747 break;
748 case EXCEPTION_SINGLE_STEP:
29fe111d
CF
749 DEBUG_EXCEPT (("gdb: Target exception SINGLE_STEP at 0x%08lx\n",
750 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1ef980b9
SC
751 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
752 break;
8227c82d 753 case EXCEPTION_ILLEGAL_INSTRUCTION:
29fe111d
CF
754 DEBUG_EXCEPT (("gdb: Target exception SINGLE_ILL at 0x%08lx\n",
755 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
8227c82d 756 ourstatus->value.sig = TARGET_SIGNAL_ILL;
8a892701 757 last_sig = SIGILL;
8227c82d 758 break;
1ef980b9 759 default:
29fe111d 760 printf_unfiltered ("gdb: unknown target exception 0x%08lx at 0x%08lx\n",
3a4b77d8 761 current_event.u.Exception.ExceptionRecord.ExceptionCode,
29fe111d 762 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress);
24e60978 763 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
1ef980b9 764 break;
24e60978 765 }
24e60978 766 exception_count++;
36339ecd 767 return 1;
24e60978
SC
768}
769
3cee93ac
CF
770/* Resume all artificially suspended threads if we are continuing
771 execution */
772static BOOL
8a892701 773child_continue (DWORD continue_status, int id)
3cee93ac
CF
774{
775 int i;
776 thread_info *th;
777 BOOL res;
778
29fe111d 779 DEBUG_EVENTS (("ContinueDebugEvent (cpid=%ld, ctid=%ld, DBG_CONTINUE);\n",
3cee93ac 780 current_event.dwProcessId, current_event.dwThreadId));
0714f9bf
SS
781 res = ContinueDebugEvent (current_event.dwProcessId,
782 current_event.dwThreadId,
783 continue_status);
1e37c281 784 continue_status = 0;
0714f9bf 785 if (res)
3a4b77d8 786 for (th = &thread_head; (th = th->next) != NULL;)
29fe111d 787 if (((id == -1) || (id == (int) th->id)) && th->suspend_count)
3cee93ac
CF
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
8a892701
CF
797/* Get the next event from the child. Return 1 if the event requires
798 handling by WFI (or whatever).
799 */
1e37c281 800static int
450005e7 801get_child_debug_event (int pid ATTRIBUTE_UNUSED, struct target_waitstatus *ourstatus)
1e37c281 802{
8a892701 803 int breakout = 0;
1e37c281 804 BOOL debug_event;
8a892701
CF
805 DWORD continue_status, event_code;
806 thread_info *th = NULL;
807 static thread_info dummy_thread_info;
450005e7 808 int retval = 0;
1e37c281 809
8a892701 810 if (!(debug_event = WaitForDebugEvent (&current_event, 1000)))
29fe111d 811 goto out;
1e37c281
JM
812
813 event_count++;
814 continue_status = DBG_CONTINUE;
1e37c281 815
8a892701 816 event_code = current_event.dwDebugEventCode;
450005e7 817 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
8a892701
CF
818
819 switch (event_code)
1e37c281
JM
820 {
821 case CREATE_THREAD_DEBUG_EVENT:
822 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
8a892701
CF
823 (unsigned) current_event.dwProcessId,
824 (unsigned) current_event.dwThreadId,
825 "CREATE_THREAD_DEBUG_EVENT"));
1e37c281 826 /* Record the existence of this thread */
8a892701
CF
827 th = child_add_thread (current_event.dwThreadId,
828 current_event.u.CreateThread.hThread);
1e37c281
JM
829 if (info_verbose)
830 printf_unfiltered ("[New %s]\n",
8a892701 831 target_pid_to_str (current_event.dwThreadId));
450005e7 832 retval = current_event.dwThreadId;
1e37c281
JM
833 break;
834
835 case EXIT_THREAD_DEBUG_EVENT:
836 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
837 (unsigned) current_event.dwProcessId,
838 (unsigned) current_event.dwThreadId,
839 "EXIT_THREAD_DEBUG_EVENT"));
1e37c281 840 child_delete_thread (current_event.dwThreadId);
8a892701 841 th = &dummy_thread_info;
1e37c281
JM
842 break;
843
844 case CREATE_PROCESS_DEBUG_EVENT:
845 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
846 (unsigned) current_event.dwProcessId,
847 (unsigned) current_event.dwThreadId,
848 "CREATE_PROCESS_DEBUG_EVENT"));
1e37c281
JM
849 current_process_handle = current_event.u.CreateProcessInfo.hProcess;
850
851 main_thread_id = inferior_pid = current_event.dwThreadId;
852 /* Add the main thread */
450005e7
CF
853 th = child_add_thread (current_event.dwProcessId,
854 current_event.u.CreateProcessInfo.hProcess);
8a892701
CF
855 th = child_add_thread (inferior_pid,
856 current_event.u.CreateProcessInfo.hThread);
450005e7 857 retval = ourstatus->value.related_pid = current_event.dwProcessId;
1e37c281
JM
858 break;
859
860 case EXIT_PROCESS_DEBUG_EVENT:
861 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
862 (unsigned) current_event.dwProcessId,
863 (unsigned) current_event.dwThreadId,
864 "EXIT_PROCESS_DEBUG_EVENT"));
1e37c281
JM
865 ourstatus->kind = TARGET_WAITKIND_EXITED;
866 ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
867 CloseHandle (current_process_handle);
450005e7 868 retval = current_event.dwProcessId;
8a892701 869 break;
1e37c281
JM
870
871 case LOAD_DLL_DEBUG_EVENT:
872 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
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);
1e37c281 877 registers_changed (); /* mark all regs invalid */
450005e7
CF
878 ourstatus->kind = TARGET_WAITKIND_LOADED;
879 ourstatus->value.integer = 0;
880 retval = current_event.dwProcessId;
1e37c281
JM
881 break;
882
883 case UNLOAD_DLL_DEBUG_EVENT:
884 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
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 */
1e37c281
JM
889
890 case EXCEPTION_DEBUG_EVENT:
891 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
892 (unsigned) current_event.dwProcessId,
893 (unsigned) current_event.dwThreadId,
894 "EXCEPTION_DEBUG_EVENT"));
450005e7
CF
895 handle_exception (ourstatus);
896 retval = current_event.dwThreadId;
1e37c281
JM
897 break;
898
8a892701 899 case OUTPUT_DEBUG_STRING_EVENT: /* message from the kernel */
1e37c281 900 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
901 (unsigned) current_event.dwProcessId,
902 (unsigned) current_event.dwThreadId,
903 "OUTPUT_DEBUG_STRING_EVENT"));
450005e7
CF
904 if (handle_output_debug_string ( ourstatus))
905 retval = current_event.dwProcessId;
1e37c281
JM
906 break;
907 default:
29fe111d
CF
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",
1e37c281
JM
912 current_event.dwDebugEventCode);
913 break;
914 }
915
450005e7 916 if (!retval)
8a892701 917 CHECK (child_continue (continue_status, -1));
450005e7
CF
918 else
919 current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
1e37c281
JM
920
921out:
450005e7 922 return retval;
1e37c281
JM
923}
924
1e37c281 925/* Wait for interesting events to occur in the target process. */
24e60978
SC
926static int
927child_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,
3cee93ac 931 which needs a current_thread->h. But some of these exceptions mark
24e60978
SC
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)
450005e7
CF
936 {
937 int retval = get_child_debug_event (pid, ourstatus);
938 if (retval)
939 return retval;
940 else
941 {
942 int detach = 0;
3cee93ac 943
450005e7
CF
944 if (ui_loop_hook != NULL)
945 detach = ui_loop_hook (0);
0714f9bf 946
450005e7
CF
947 if (detach)
948 child_kill_inferior ();
949 }
950 }
24e60978
SC
951}
952
24e60978
SC
953/* Attach to process PID, then initialize for debugging it. */
954
955static void
956child_attach (args, from_tty)
957 char *args;
958 int from_tty;
959{
960 BOOL ok;
961
962 if (!args)
963 error_no_arg ("process-id to attach");
964
3cee93ac 965 current_event.dwProcessId = strtoul (args, 0, 0);
24e60978 966
3cee93ac 967 ok = DebugActiveProcess (current_event.dwProcessId);
24e60978
SC
968
969 if (!ok)
970 error ("Can't attach to process.");
971
24e60978
SC
972 exception_count = 0;
973 event_count = 0;
974
450005e7
CF
975 child_init_thread_list ();
976 child_clear_solibs ();
977
24e60978
SC
978 if (from_tty)
979 {
980 char *exec_file = (char *) get_exec_file (0);
981
982 if (exec_file)
983 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
3cee93ac 984 target_pid_to_str (current_event.dwProcessId));
24e60978
SC
985 else
986 printf_unfiltered ("Attaching to %s\n",
3cee93ac 987 target_pid_to_str (current_event.dwProcessId));
24e60978
SC
988
989 gdb_flush (gdb_stdout);
990 }
991
24e60978
SC
992 push_target (&child_ops);
993}
994
24e60978 995static void
29fe111d 996child_detach (char *args ATTRIBUTE_UNUSED, int from_tty)
24e60978
SC
997{
998 if (from_tty)
999 {
1000 char *exec_file = get_exec_file (0);
1001 if (exec_file == 0)
1002 exec_file = "";
1003 printf_unfiltered ("Detaching from program: %s %s\n", exec_file,
1004 target_pid_to_str (inferior_pid));
1005 gdb_flush (gdb_stdout);
1006 }
1007 inferior_pid = 0;
1008 unpush_target (&child_ops);
1009}
1010
24e60978
SC
1011/* Print status information about what we're accessing. */
1012
1013static void
29fe111d 1014child_files_info (struct target_ops *ignore ATTRIBUTE_UNUSED)
24e60978
SC
1015{
1016 printf_unfiltered ("\tUsing the running image of %s %s.\n",
1017 attach_flag ? "attached" : "child", target_pid_to_str (inferior_pid));
1018}
1019
1020/* ARGSUSED */
1021static void
29fe111d 1022child_open (char *arg ATTRIBUTE_UNUSED, int from_tty ATTRIBUTE_UNUSED)
24e60978
SC
1023{
1024 error ("Use the \"run\" command to start a Unix child process.");
1025}
1026
eb708f2e 1027/* Start an inferior win32 child process and sets inferior_pid to its pid.
24e60978
SC
1028 EXEC_FILE is the file to run.
1029 ALLARGS is a string containing the arguments to the program.
1030 ENV is the environment vector to pass. Errors reported with error(). */
1031
24e60978
SC
1032static void
1033child_create_inferior (exec_file, allargs, env)
1034 char *exec_file;
1035 char *allargs;
1036 char **env;
1037{
1750a5ef
SC
1038 char real_path[MAXPATHLEN];
1039 char *winenv;
1040 char *temp;
3a4b77d8 1041 int envlen;
1750a5ef 1042 int i;
24e60978
SC
1043 STARTUPINFO si;
1044 PROCESS_INFORMATION pi;
1045 struct target_waitstatus dummy;
1046 BOOL ret;
1047 DWORD flags;
eb708f2e 1048 char *args;
450005e7 1049 extern int stop_after_trap;
24e60978
SC
1050
1051 if (!exec_file)
450005e7 1052 error ("No executable specified, use `target exec'.\n");
24e60978
SC
1053
1054 memset (&si, 0, sizeof (si));
1055 si.cb = sizeof (si);
1056
29fe111d 1057 cygwin_conv_to_win32_path (exec_file, real_path);
24e60978 1058
3cee93ac 1059 flags = DEBUG_ONLY_THIS_PROCESS;
24e60978
SC
1060
1061 if (new_group)
1062 flags |= CREATE_NEW_PROCESS_GROUP;
1063
1064 if (new_console)
1065 flags |= CREATE_NEW_CONSOLE;
1066
3d78f532
SC
1067 args = alloca (strlen (real_path) + strlen (allargs) + 2);
1068
1069 strcpy (args, real_path);
eb708f2e 1070
eb708f2e
SC
1071 strcat (args, " ");
1072 strcat (args, allargs);
1073
e88c49c3
DE
1074 /* Prepare the environment vars for CreateProcess. */
1075 {
1076 /* This code use to assume all env vars were file names and would
1077 translate them all to win32 style. That obviously doesn't work in the
2dcfc9c7
DE
1078 general case. The current rule is that we only translate PATH.
1079 We need to handle PATH because we're about to call CreateProcess and
1080 it uses PATH to find DLL's. Fortunately PATH has a well-defined value
1081 in both posix and win32 environments. cygwin.dll will change it back
1082 to posix style if necessary. */
e88c49c3
DE
1083
1084 static const char *conv_path_names[] =
3a4b77d8
JM
1085 {
1086 "PATH=",
1087 0
1088 };
e88c49c3
DE
1089
1090 /* CreateProcess takes the environment list as a null terminated set of
1091 strings (i.e. two nulls terminate the list). */
1092
1093 /* Get total size for env strings. */
1094 for (envlen = 0, i = 0; env[i] && *env[i]; i++)
1095 {
2dcfc9c7 1096 int j, len;
e88c49c3 1097
2dcfc9c7
DE
1098 for (j = 0; conv_path_names[j]; j++)
1099 {
1100 len = strlen (conv_path_names[j]);
1101 if (strncmp (conv_path_names[j], env[i], len) == 0)
e88c49c3 1102 {
29fe111d 1103 if (cygwin_posix_path_list_p (env[i] + len))
2dcfc9c7 1104 envlen += len
29fe111d 1105 + cygwin_posix_to_win32_path_list_buf_size (env[i] + len);
2dcfc9c7
DE
1106 else
1107 envlen += strlen (env[i]) + 1;
1108 break;
e88c49c3 1109 }
e88c49c3 1110 }
2dcfc9c7 1111 if (conv_path_names[j] == NULL)
e88c49c3
DE
1112 envlen += strlen (env[i]) + 1;
1113 }
1114
1115 winenv = alloca (envlen + 1);
1116
1117 /* Copy env strings into new buffer. */
3cee93ac 1118 for (temp = winenv, i = 0; env[i] && *env[i]; i++)
e88c49c3 1119 {
2dcfc9c7 1120 int j, len;
e88c49c3 1121
2dcfc9c7
DE
1122 for (j = 0; conv_path_names[j]; j++)
1123 {
1124 len = strlen (conv_path_names[j]);
1125 if (strncmp (conv_path_names[j], env[i], len) == 0)
e88c49c3 1126 {
29fe111d 1127 if (cygwin_posix_path_list_p (env[i] + len))
e88c49c3
DE
1128 {
1129 memcpy (temp, env[i], len);
29fe111d 1130 cygwin_posix_to_win32_path_list (env[i] + len, temp + len);
e88c49c3 1131 }
2dcfc9c7
DE
1132 else
1133 strcpy (temp, env[i]);
1134 break;
e88c49c3 1135 }
e88c49c3 1136 }
2dcfc9c7 1137 if (conv_path_names[j] == NULL)
e88c49c3 1138 strcpy (temp, env[i]);
2dcfc9c7 1139
e88c49c3
DE
1140 temp += strlen (temp) + 1;
1141 }
1142
1143 /* Final nil string to terminate new env. */
1144 *temp = 0;
1145 }
1750a5ef 1146
1750a5ef 1147 ret = CreateProcess (0,
3a4b77d8 1148 args, /* command line */
24e60978
SC
1149 NULL, /* Security */
1150 NULL, /* thread */
1151 TRUE, /* inherit handles */
1152 flags, /* start flags */
1750a5ef 1153 winenv,
24e60978
SC
1154 NULL, /* current directory */
1155 &si,
1156 &pi);
1157 if (!ret)
3a4b77d8 1158 error ("Error creating process %s, (error %d)\n", exec_file, GetLastError ());
24e60978
SC
1159
1160 exception_count = 0;
1161 event_count = 0;
1162
3cee93ac
CF
1163 current_process_handle = pi.hProcess;
1164 current_event.dwProcessId = pi.dwProcessId;
1165 memset (&current_event, 0, sizeof (current_event));
1166 inferior_pid = current_event.dwThreadId = pi.dwThreadId;
24e60978 1167 push_target (&child_ops);
3cee93ac 1168 child_init_thread_list ();
450005e7 1169 child_clear_solibs ();
24e60978 1170 clear_proceed_status ();
450005e7 1171 init_wait_for_inferior ();
24e60978
SC
1172 target_terminal_init ();
1173 target_terminal_inferior ();
29fe111d 1174 last_sig = 0;
24e60978 1175
450005e7
CF
1176 while (1)
1177 {
1178 stop_after_trap = 1;
1179 wait_for_inferior ();
1180 if (stop_signal != TARGET_SIGNAL_TRAP)
1181 resume (0, stop_signal);
1182 else
1183 break;
1184 }
1185 stop_after_trap = 0;
d3a09475 1186
8a892701 1187 /* child_continue (DBG_CONTINUE, -1);*/
1e37c281 1188 proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
24e60978
SC
1189}
1190
1191static void
1192child_mourn_inferior ()
1193{
8a892701 1194 (void) child_continue (DBG_CONTINUE, -1);
24e60978
SC
1195 unpush_target (&child_ops);
1196 generic_mourn_inferior ();
1197}
1198
24e60978
SC
1199/* Send a SIGINT to the process group. This acts just like the user typed a
1200 ^C on the controlling terminal. */
1201
b607efe7 1202static void
24e60978
SC
1203child_stop ()
1204{
1ef980b9 1205 DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
1e37c281 1206 CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
3a4b77d8 1207 registers_changed (); /* refresh register state */
24e60978
SC
1208}
1209
1210int
eb708f2e 1211child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
29fe111d 1212 int write, struct target_ops *target ATTRIBUTE_UNUSED)
24e60978
SC
1213{
1214 DWORD done;
1215 if (write)
1216 {
29fe111d
CF
1217 DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08lx\n",
1218 len, (DWORD) memaddr));
3cee93ac
CF
1219 WriteProcessMemory (current_process_handle, (LPVOID) memaddr, our,
1220 len, &done);
1221 FlushInstructionCache (current_process_handle, (LPCVOID) memaddr, len);
24e60978
SC
1222 }
1223 else
1224 {
29fe111d
CF
1225 DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08lx\n",
1226 len, (DWORD) memaddr));
3cee93ac
CF
1227 ReadProcessMemory (current_process_handle, (LPCVOID) memaddr, our, len,
1228 &done);
24e60978
SC
1229 }
1230 return done;
1231}
1232
1233void
1234child_kill_inferior (void)
1235{
3cee93ac
CF
1236 CHECK (TerminateProcess (current_process_handle, 0));
1237
b5edcb45
ILT
1238 for (;;)
1239 {
8a892701 1240 if (!child_continue (DBG_CONTINUE, -1))
b5edcb45 1241 break;
3cee93ac 1242 if (!WaitForDebugEvent (&current_event, INFINITE))
b5edcb45 1243 break;
3cee93ac 1244 if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
b5edcb45
ILT
1245 break;
1246 }
1247
3cee93ac
CF
1248 CHECK (CloseHandle (current_process_handle));
1249
1250 /* this may fail in an attached process so don't check. */
1251 (void) CloseHandle (current_thread->h);
3a4b77d8 1252 target_mourn_inferior (); /* or just child_mourn_inferior? */
24e60978
SC
1253}
1254
1255void
3cee93ac 1256child_resume (int pid, int step, enum target_signal sig)
24e60978 1257{
3cee93ac 1258 thread_info *th;
8a892701
CF
1259 DWORD continue_status = last_sig > 0 && last_sig < NSIG ?
1260 DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE;
1261
1262 last_sig = 0;
24e60978 1263
3cee93ac
CF
1264 DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, sig=%d);\n",
1265 pid, step, sig));
1266
1267 /* Get context for currently selected thread */
1268 th = thread_rec (current_event.dwThreadId, FALSE);
450005e7 1269 if (th)
24e60978 1270 {
450005e7
CF
1271 if (step)
1272 {
1273 /* Single step by setting t bit */
1274 child_fetch_inferior_registers (PS_REGNUM);
1275 th->context.EFlags |= FLAG_TRACE_BIT;
1276 }
24e60978 1277
450005e7
CF
1278 if (th->context.ContextFlags)
1279 {
1280 CHECK (SetThreadContext (th->h, &th->context));
1281 th->context.ContextFlags = 0;
1282 }
24e60978
SC
1283 }
1284
3cee93ac
CF
1285 /* Allow continuing with the same signal that interrupted us.
1286 Otherwise complain. */
24e60978 1287
8a892701 1288 child_continue (continue_status, pid);
24e60978
SC
1289}
1290
1291static void
1292child_prepare_to_store ()
1293{
1294 /* Do nothing, since we can store individual regs */
1295}
1296
1297static int
1298child_can_run ()
1299{
1300 return 1;
1301}
1302
1303static void
1304child_close ()
1305{
1ef980b9 1306 DEBUG_EVENTS (("gdb: child_close, inferior_pid=%d\n", inferior_pid));
24e60978 1307}
1ef980b9 1308
3a4b77d8 1309struct target_ops child_ops;
c719b714 1310
3a4b77d8
JM
1311static void
1312init_child_ops (void)
24e60978 1313{
3a4b77d8
JM
1314 child_ops.to_shortname = "child";
1315 child_ops.to_longname = "Win32 child process";
1316 child_ops.to_doc = "Win32 child process (started by the \"run\" command).";
1317 child_ops.to_open = child_open;
1318 child_ops.to_close = child_close;
1319 child_ops.to_attach = child_attach;
1320 child_ops.to_detach = child_detach;
1321 child_ops.to_resume = child_resume;
1322 child_ops.to_wait = child_wait;
1323 child_ops.to_fetch_registers = child_fetch_inferior_registers;
1324 child_ops.to_store_registers = child_store_inferior_registers;
1325 child_ops.to_prepare_to_store = child_prepare_to_store;
1326 child_ops.to_xfer_memory = child_xfer_memory;
1327 child_ops.to_files_info = child_files_info;
1328 child_ops.to_insert_breakpoint = memory_insert_breakpoint;
1329 child_ops.to_remove_breakpoint = memory_remove_breakpoint;
1330 child_ops.to_terminal_init = terminal_init_inferior;
1331 child_ops.to_terminal_inferior = terminal_inferior;
1332 child_ops.to_terminal_ours_for_output = terminal_ours_for_output;
1333 child_ops.to_terminal_ours = terminal_ours;
1334 child_ops.to_terminal_info = child_terminal_info;
1335 child_ops.to_kill = child_kill_inferior;
1336 child_ops.to_load = 0;
1337 child_ops.to_lookup_symbol = 0;
1338 child_ops.to_create_inferior = child_create_inferior;
1339 child_ops.to_mourn_inferior = child_mourn_inferior;
1340 child_ops.to_can_run = child_can_run;
1341 child_ops.to_notice_signals = 0;
1342 child_ops.to_thread_alive = win32_child_thread_alive;
d3a09475 1343 child_ops.to_pid_to_str = cygwin_pid_to_str;
3a4b77d8
JM
1344 child_ops.to_stop = child_stop;
1345 child_ops.to_stratum = process_stratum;
1346 child_ops.DONT_USE = 0;
1347 child_ops.to_has_all_memory = 1;
1348 child_ops.to_has_memory = 1;
1349 child_ops.to_has_stack = 1;
1350 child_ops.to_has_registers = 1;
1351 child_ops.to_has_execution = 1;
1352 child_ops.to_sections = 0;
1353 child_ops.to_sections_end = 0;
1354 child_ops.to_magic = OPS_MAGIC;
c719b714 1355}
24e60978
SC
1356
1357void
1358_initialize_inftarg ()
1359{
3a4b77d8 1360 init_child_ops ();
1ef980b9 1361
450005e7
CF
1362 add_com ("dll-symbols", class_files, dll_symbol_command,
1363 "Load dll library symbols from FILE.");
1364
1365 add_com_alias ("sharedlibrary", "dll-symbols", class_alias, 1);
1366
1367 add_show_from_set (add_set_cmd ("new-console", class_support, var_boolean,
24e60978
SC
1368 (char *) &new_console,
1369 "Set creation of new console when creating child process.",
1370 &setlist),
1371 &showlist);
1372
450005e7 1373 add_show_from_set (add_set_cmd ("new-group", class_support, var_boolean,
24e60978
SC
1374 (char *) &new_group,
1375 "Set creation of new group when creating child process.",
1376 &setlist),
1377 &showlist);
1378
450005e7 1379 add_show_from_set (add_set_cmd ("debugexec", class_support, var_boolean,
1ef980b9
SC
1380 (char *) &debug_exec,
1381 "Set whether to display execution in child process.",
1382 &setlist),
1383 &showlist);
1384
450005e7 1385 add_show_from_set (add_set_cmd ("debugevents", class_support, var_boolean,
1ef980b9
SC
1386 (char *) &debug_events,
1387 "Set whether to display kernel events in child process.",
1388 &setlist),
1389 &showlist);
1390
450005e7 1391 add_show_from_set (add_set_cmd ("debugmemory", class_support, var_boolean,
1ef980b9
SC
1392 (char *) &debug_memory,
1393 "Set whether to display memory accesses in child process.",
1394 &setlist),
1395 &showlist);
1396
450005e7 1397 add_show_from_set (add_set_cmd ("debugexceptions", class_support, var_boolean,
1ef980b9 1398 (char *) &debug_exceptions,
450005e7 1399 "Set whether to display kernel exceptions in child process.",
1ef980b9
SC
1400 &setlist),
1401 &showlist);
1402
450005e7
CF
1403 add_info ("dll", info_dll_command, "Status of loaded DLLs.");
1404 add_info_alias ("sharedlibrary", "dll", 1);
1405
24e60978
SC
1406 add_target (&child_ops);
1407}
3cee93ac
CF
1408
1409/* Determine if the thread referenced by "pid" is alive
1410 by "polling" it. If WaitForSingleObject returns WAIT_OBJECT_0
1411 it means that the pid has died. Otherwise it is assumed to be alive. */
1412static int
bc8bd256 1413win32_child_thread_alive (int pid)
3cee93ac 1414{
3a4b77d8
JM
1415 return WaitForSingleObject (thread_rec (pid, FALSE)->h, 0) == WAIT_OBJECT_0 ?
1416 FALSE : TRUE;
3cee93ac
CF
1417}
1418
1419/* Convert pid to printable format. */
1420char *
1421cygwin_pid_to_str (int pid)
1422{
1423 static char buf[80];
29fe111d 1424 if ((DWORD) pid == current_event.dwProcessId)
3cee93ac
CF
1425 sprintf (buf, "process %d", pid);
1426 else
29fe111d 1427 sprintf (buf, "thread %ld.0x%x", current_event.dwProcessId, pid);
3cee93ac
CF
1428 return buf;
1429}
This page took 0.315712 seconds and 4 git commands to generate.