2000-08-21 H.J. Lu <hjl@gnu.org>
[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
9d3789f7
CF
57enum
58{
59 FLAG_TRACE_BIT = 0x100,
60 CONTEXT_DEBUGGER = (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
61};
0714f9bf
SS
62#endif
63
3cee93ac
CF
64/* The string sent by cygwin when it processes a signal.
65 FIXME: This should be in a cygwin include file. */
66#define CYGWIN_SIGNAL_STRING "cygwin: signal"
67
29fe111d 68#define CHECK(x) check (x, __FILE__,__LINE__)
1ef980b9
SC
69#define DEBUG_EXEC(x) if (debug_exec) printf x
70#define DEBUG_EVENTS(x) if (debug_events) printf x
71#define DEBUG_MEM(x) if (debug_memory) printf x
72#define DEBUG_EXCEPT(x) if (debug_exceptions) printf x
24e60978
SC
73
74/* Forward declaration */
75extern struct target_ops child_ops;
76
a14ed312
KB
77static void child_stop (void);
78static int win32_child_thread_alive (int);
79void child_kill_inferior (void);
3cee93ac 80
8a892701
CF
81static int last_sig = 0; /* Set if a signal was received from the
82 debugged process */
3cee93ac
CF
83/* Thread information structure used to track information that is
84 not available in gdb's thread structure. */
85typedef struct thread_info_struct
3a4b77d8
JM
86 {
87 struct thread_info_struct *next;
88 DWORD id;
89 HANDLE h;
90 char *name;
91 int suspend_count;
92 CONTEXT context;
1e37c281
JM
93 STACKFRAME sf;
94 } thread_info;
95
29fe111d 96static thread_info thread_head;
24e60978 97
24e60978
SC
98/* The process and thread handles for the above context. */
99
3cee93ac
CF
100static DEBUG_EVENT current_event; /* The current debug event from
101 WaitForDebugEvent */
102static HANDLE current_process_handle; /* Currently executing process */
103static thread_info *current_thread; /* Info on currently selected thread */
3a4b77d8 104static DWORD main_thread_id; /* Thread ID of the main thread */
24e60978
SC
105
106/* Counts of things. */
107static int exception_count = 0;
108static int event_count = 0;
109
110/* User options. */
111static int new_console = 0;
1e37c281 112static int new_group = 1;
3a4b77d8
JM
113static int debug_exec = 0; /* show execution */
114static int debug_events = 0; /* show events from kernel */
115static int debug_memory = 0; /* show target memory accesses */
1ef980b9 116static int debug_exceptions = 0; /* show target exceptions */
24e60978
SC
117
118/* This vector maps GDB's idea of a register's number into an address
3cee93ac 119 in the win32 exception context vector.
24e60978 120
3cee93ac 121 It also contains the bit mask needed to load the register in question.
24e60978
SC
122
123 One day we could read a reg, we could inspect the context we
124 already have loaded, if it doesn't have the bit set that we need,
125 we read that set of registers in using GetThreadContext. If the
126 context already contains what we need, we just unpack it. Then to
127 write a register, first we have to ensure that the context contains
128 the other regs of the group, and then we copy the info in and set
129 out bit. */
130
3cee93ac
CF
131#define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
132static const int mappings[] =
24e60978 133{
3a4b77d8
JM
134 context_offset (Eax),
135 context_offset (Ecx),
136 context_offset (Edx),
137 context_offset (Ebx),
138 context_offset (Esp),
139 context_offset (Ebp),
140 context_offset (Esi),
141 context_offset (Edi),
142 context_offset (Eip),
143 context_offset (EFlags),
144 context_offset (SegCs),
145 context_offset (SegSs),
146 context_offset (SegDs),
147 context_offset (SegEs),
148 context_offset (SegFs),
149 context_offset (SegGs),
150 context_offset (FloatSave.RegisterArea[0 * 10]),
151 context_offset (FloatSave.RegisterArea[1 * 10]),
152 context_offset (FloatSave.RegisterArea[2 * 10]),
153 context_offset (FloatSave.RegisterArea[3 * 10]),
154 context_offset (FloatSave.RegisterArea[4 * 10]),
155 context_offset (FloatSave.RegisterArea[5 * 10]),
156 context_offset (FloatSave.RegisterArea[6 * 10]),
157 context_offset (FloatSave.RegisterArea[7 * 10]),
1e37c281
JM
158 context_offset (FloatSave.ControlWord),
159 context_offset (FloatSave.StatusWord),
160 context_offset (FloatSave.TagWord),
161 context_offset (FloatSave.ErrorSelector),
162 context_offset (FloatSave.ErrorOffset),
163 context_offset (FloatSave.DataSelector),
164 context_offset (FloatSave.DataOffset),
d3a09475 165 context_offset (FloatSave.ErrorSelector)
24e60978
SC
166};
167
d3a09475
JM
168#undef context_offset
169
24e60978
SC
170/* This vector maps the target's idea of an exception (extracted
171 from the DEBUG_EVENT structure) to GDB's idea. */
172
173struct xlate_exception
174 {
175 int them;
176 enum target_signal us;
177 };
178
24e60978
SC
179static const struct xlate_exception
180 xlate[] =
181{
182 {EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV},
9cbf6c0e 183 {STATUS_STACK_OVERFLOW, TARGET_SIGNAL_SEGV},
24e60978
SC
184 {EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP},
185 {DBG_CONTROL_C, TARGET_SIGNAL_INT},
186 {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP},
187 {-1, -1}};
188
3cee93ac
CF
189/* Find a thread record given a thread id.
190 If get_context then also retrieve the context for this
191 thread. */
192static thread_info *
193thread_rec (DWORD id, int get_context)
24e60978 194{
3cee93ac
CF
195 thread_info *th;
196
3a4b77d8 197 for (th = &thread_head; (th = th->next) != NULL;)
3cee93ac
CF
198 if (th->id == id)
199 {
200 if (!th->suspend_count && get_context)
201 {
8a892701 202 if (get_context > 0 && id != current_event.dwThreadId)
3cee93ac
CF
203 th->suspend_count = SuspendThread (th->h) + 1;
204 else if (get_context < 0)
205 th->suspend_count = -1;
206
207 th->context.ContextFlags = CONTEXT_DEBUGGER;
208 GetThreadContext (th->h, &th->context);
209 }
210 return th;
211 }
212
213 return NULL;
214}
215
216/* Add a thread to the thread list */
217static thread_info *
3a4b77d8 218child_add_thread (DWORD id, HANDLE h)
3cee93ac
CF
219{
220 thread_info *th;
221
222 if ((th = thread_rec (id, FALSE)))
223 return th;
224
225 th = (thread_info *) xmalloc (sizeof (*th));
3a4b77d8 226 memset (th, 0, sizeof (*th));
3cee93ac
CF
227 th->id = id;
228 th->h = h;
229 th->next = thread_head.next;
230 thread_head.next = th;
231 add_thread (id);
232 return th;
24e60978
SC
233}
234
3cee93ac
CF
235/* Clear out any old thread list and reintialize it to a
236 pristine state. */
24e60978 237static void
fba45db2 238child_init_thread_list (void)
24e60978 239{
3cee93ac
CF
240 thread_info *th = &thread_head;
241
242 DEBUG_EVENTS (("gdb: child_init_thread_list\n"));
243 init_thread_list ();
244 while (th->next != NULL)
24e60978 245 {
3cee93ac
CF
246 thread_info *here = th->next;
247 th->next = here->next;
248 (void) CloseHandle (here->h);
249 free (here);
24e60978 250 }
3cee93ac
CF
251}
252
253/* Delete a thread from the list of threads */
254static void
255child_delete_thread (DWORD id)
256{
257 thread_info *th;
258
259 if (info_verbose)
260 printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (id));
261 delete_thread (id);
262
263 for (th = &thread_head;
264 th->next != NULL && th->next->id != id;
265 th = th->next)
266 continue;
267
268 if (th->next != NULL)
24e60978 269 {
3cee93ac
CF
270 thread_info *here = th->next;
271 th->next = here->next;
272 CloseHandle (here->h);
273 free (here);
24e60978
SC
274 }
275}
276
277static void
3cee93ac
CF
278check (BOOL ok, const char *file, int line)
279{
280 if (!ok)
29fe111d 281 printf_filtered ("error return %s:%d was %lu\n", file, line, GetLastError ());
3cee93ac
CF
282}
283
284static void
285do_child_fetch_inferior_registers (int r)
24e60978 286{
1e37c281
JM
287 char *context_offset = ((char *) &current_thread->context) + mappings[r];
288 long l;
289 if (r == FCS_REGNUM)
290 {
291 l = *((long *)context_offset) & 0xffff;
292 supply_register (r, (char *) &l);
293 }
294 else if (r == FOP_REGNUM)
295 {
296 l = (*((long *)context_offset) >> 16) & ((1 << 11) - 1);
297 supply_register (r, (char *) &l);
298 }
299 else if (r >= 0)
d3a09475 300 supply_register (r, context_offset);
3cee93ac 301 else
24e60978
SC
302 {
303 for (r = 0; r < NUM_REGS; r++)
3cee93ac 304 do_child_fetch_inferior_registers (r);
24e60978 305 }
3cee93ac
CF
306}
307
308static void
309child_fetch_inferior_registers (int r)
310{
311 current_thread = thread_rec (inferior_pid, TRUE);
312 do_child_fetch_inferior_registers (r);
313}
314
315static void
316do_child_store_inferior_registers (int r)
317{
318 if (r >= 0)
319 read_register_gen (r, ((char *) &current_thread->context) + mappings[r]);
24e60978
SC
320 else
321 {
3cee93ac
CF
322 for (r = 0; r < NUM_REGS; r++)
323 do_child_store_inferior_registers (r);
24e60978
SC
324 }
325}
326
3cee93ac
CF
327/* Store a new register value into the current thread context */
328static void
329child_store_inferior_registers (int r)
330{
331 current_thread = thread_rec (inferior_pid, TRUE);
332 do_child_store_inferior_registers (r);
333}
24e60978 334
1e37c281
JM
335#include <psapi.h>
336static int psapi_loaded = 0;
337static HMODULE psapi_module_handle = NULL;
338static BOOL WINAPI (*psapi_EnumProcessModules)(HANDLE, HMODULE*, DWORD, LPDWORD)= NULL;
339static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO, DWORD)= NULL;
340static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD)= NULL;
341
342int psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
343{
344 DWORD len;
345 MODULEINFO mi;
346 int i;
347 HMODULE dh_buf [ 1 ];
348 HMODULE* DllHandle = dh_buf;
349 DWORD cbNeeded;
350 BOOL ok;
351
352 if (!psapi_loaded ||
353 psapi_EnumProcessModules == NULL ||
354 psapi_GetModuleInformation == NULL ||
355 psapi_GetModuleFileNameExA == NULL)
356 {
357 if (psapi_loaded)goto failed;
358 psapi_loaded = 1;
359 psapi_module_handle = LoadLibrary ("psapi.dll");
360 if (!psapi_module_handle)
361 {
362 /* printf_unfiltered ("error loading psapi.dll: %u", GetLastError ());*/
363 goto failed;
364 }
365 psapi_EnumProcessModules = GetProcAddress (psapi_module_handle, "EnumProcessModules" );
366 psapi_GetModuleInformation = GetProcAddress (psapi_module_handle, "GetModuleInformation");
367 psapi_GetModuleFileNameExA = (void *) GetProcAddress (psapi_module_handle,
368 "GetModuleFileNameExA");
369 if (psapi_EnumProcessModules == NULL ||
370 psapi_GetModuleInformation == NULL ||
371 psapi_GetModuleFileNameExA == NULL)
372 goto failed;
373 }
374
375 cbNeeded = 0;
376 ok = (*psapi_EnumProcessModules) (current_process_handle,
377 DllHandle,
378 sizeof (HMODULE),
379 &cbNeeded);
380
381 if (!ok || !cbNeeded)
382 goto failed;
383
384 DllHandle = (HMODULE*) alloca (cbNeeded);
385 if (!DllHandle)
386 goto failed;
387
388 ok = (*psapi_EnumProcessModules) (current_process_handle,
389 DllHandle,
390 cbNeeded,
391 &cbNeeded);
392 if (!ok)
393 goto failed;
394
29fe111d 395 for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
1e37c281
JM
396 {
397 if (!(*psapi_GetModuleInformation) (current_process_handle,
398 DllHandle [i],
399 &mi,
400 sizeof (mi)))
401 error ("Can't get module info");
402
403 len = (*psapi_GetModuleFileNameExA) (current_process_handle,
404 DllHandle [i],
405 dll_name_ret,
406 MAX_PATH);
407 if (len == 0)
29fe111d 408 error ("Error getting dll name: %u\n", GetLastError ());
1e37c281
JM
409
410 if ((DWORD) (mi.lpBaseOfDll) == BaseAddress)
411 return 1;
412 }
413
414failed:
415 dll_name_ret[0] = '\0';
416 return 0;
417}
418
450005e7
CF
419/* Encapsulate the information required in a call to
420 symbol_file_add_args */
8a892701
CF
421struct safe_symbol_file_add_args
422{
423 char *name;
424 int from_tty;
425 struct section_addr_info *addrs;
426 int mainline;
427 int flags;
7c5c87c0 428 struct ui_file *err, *out;
8a892701
CF
429 struct objfile *ret;
430};
431
450005e7
CF
432/* Call symbol_file_add with stderr redirected. We don't care if there
433 are errors. */
8a892701
CF
434static int
435safe_symbol_file_add_stub (void *argv)
436{
437#define p ((struct safe_symbol_file_add_args *)argv)
438 p->ret = symbol_file_add (p->name, p->from_tty, p->addrs, p->mainline, p->flags);
439 return !!p->ret;
440#undef p
441}
442
450005e7 443/* Restore gdb's stderr after calling symbol_file_add */
8a892701 444static void
7c5c87c0 445safe_symbol_file_add_cleanup (void *p)
8a892701 446{
9d3789f7 447# define sp ((struct safe_symbol_file_add_args *)p)
450005e7 448 gdb_flush (gdb_stderr);
7c5c87c0 449 gdb_flush (gdb_stdout);
8a892701 450 ui_file_delete (gdb_stderr);
7c5c87c0
CF
451 ui_file_delete (gdb_stdout);
452 gdb_stderr = sp->err;
9d3789f7
CF
453 gdb_stdout = sp->out;
454# undef sp
8a892701
CF
455}
456
450005e7 457/* symbol_file_add wrapper that prevents errors from being displayed. */
8a892701
CF
458static struct objfile *
459safe_symbol_file_add (char *name, int from_tty,
460 struct section_addr_info *addrs,
461 int mainline, int flags)
462
463{
464 struct safe_symbol_file_add_args p;
465 struct cleanup *cleanup;
466
7c5c87c0 467 cleanup = make_cleanup (safe_symbol_file_add_cleanup, &p);
8a892701 468
7c5c87c0
CF
469 p.err = gdb_stderr;
470 p.out = gdb_stdout;
450005e7 471 gdb_flush (gdb_stderr);
7c5c87c0 472 gdb_flush (gdb_stdout);
8a892701 473 gdb_stderr = ui_file_new ();
7c5c87c0 474 gdb_stdout = ui_file_new ();
8a892701
CF
475 p.name = name;
476 p.from_tty = from_tty;
477 p.addrs = addrs;
478 p.mainline = mainline;
479 p.flags = flags;
480 catch_errors (safe_symbol_file_add_stub, &p, "", RETURN_MASK_ERROR);
481
482 do_cleanups (cleanup);
483 return p.ret;
484}
485
450005e7
CF
486/* Maintain a linked list of "so" information. */
487struct so_stuff
488{
489 struct so_stuff *next, **last;
490 DWORD load_addr;
491 char name[0];
492} solib_start, *solib_end;
493
494/* Remember the maximum DLL length for printing in info dll command. */
495int max_dll_name_len;
496
24e60978
SC
497/* Wait for child to do something. Return pid of child, or -1 in case
498 of error; store status through argument pointer OURSTATUS. */
1750a5ef 499static int
29fe111d 500handle_load_dll (PTR dummy ATTRIBUTE_UNUSED)
24e60978 501{
3a4b77d8 502 LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
24e60978
SC
503 DWORD dll_name_ptr;
504 DWORD done;
3cee93ac 505 char dll_buf[MAX_PATH + 1];
9d3789f7 506 struct so_stuff *so;
450005e7 507 char *dll_name = NULL;
450005e7
CF
508 int len;
509 char *p;
3cee93ac 510
3a4b77d8 511 dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
3cee93ac 512
1e37c281
JM
513 if (!psapi_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf))
514 dll_buf[0] = dll_buf[sizeof(dll_buf) - 1] = '\0';
3cee93ac 515
1e37c281 516 dll_name = dll_buf;
24e60978 517
3cee93ac
CF
518 /* Attempt to read the name of the dll that was detected.
519 This is documented to work only when actively debugging
520 a program. It will not work for attached processes. */
521 if (dll_name == NULL || *dll_name == '\0')
24e60978 522 {
29fe111d 523 DWORD size = event->fUnicode ? sizeof (WCHAR) : sizeof (char);
24e60978
SC
524 int len = 0;
525 char b[2];
3cee93ac
CF
526
527 ReadProcessMemory (current_process_handle,
528 (LPCVOID) event->lpImageName,
529 (char *) &dll_name_ptr,
530 sizeof (dll_name_ptr), &done);
531
532 /* See if we could read the address of a string, and that the
3a4b77d8 533 address isn't null. */
3cee93ac
CF
534
535 if (done != sizeof (dll_name_ptr) || !dll_name_ptr)
536 return 1;
537
24e60978
SC
538 do
539 {
3cee93ac
CF
540 ReadProcessMemory (current_process_handle,
541 (LPCVOID) (dll_name_ptr + len * size),
24e60978
SC
542 &b,
543 size,
544 &done);
545 len++;
546 }
547 while ((b[0] != 0 || b[size - 1] != 0) && done == size);
548
24e60978
SC
549 dll_name = alloca (len);
550
3cee93ac 551 if (event->fUnicode)
24e60978
SC
552 {
553 WCHAR *unicode_dll_name = (WCHAR *) alloca (len * sizeof (WCHAR));
3cee93ac
CF
554 ReadProcessMemory (current_process_handle,
555 (LPCVOID) dll_name_ptr,
24e60978
SC
556 unicode_dll_name,
557 len * sizeof (WCHAR),
558 &done);
559
560 WideCharToMultiByte (CP_ACP, 0,
561 unicode_dll_name, len,
562 dll_name, len, 0, 0);
563 }
564 else
565 {
3cee93ac
CF
566 ReadProcessMemory (current_process_handle,
567 (LPCVOID) dll_name_ptr,
24e60978
SC
568 dll_name,
569 len,
570 &done);
571 }
24e60978 572 }
3cee93ac
CF
573
574 if (!dll_name)
575 return 1;
576
29fe111d
CF
577 (void) strlwr (dll_name);
578
3cee93ac
CF
579 while ((p = strchr (dll_name, '\\')))
580 *p = '/';
581
450005e7
CF
582 so = (struct so_stuff *) xmalloc (sizeof (struct so_stuff) + strlen (dll_name) + 8 + 2);
583 so->load_addr = (DWORD) event->lpBaseOfDll + 0x1000;
584 strcpy (so->name, dll_name);
585
586 solib_end->next = so;
587 solib_end = so;
588 so->next = NULL;
589
590 len = strlen (dll_name);
591 if (len > max_dll_name_len)
592 max_dll_name_len = len;
593
594 return 1;
595}
596
597/* Return name of last loaded DLL. */
598char *
9d3789f7 599child_solib_loaded_library_pathname (int pid ATTRIBUTE_UNUSED)
450005e7
CF
600{
601 return !solib_end || !solib_end->name[0]? NULL : solib_end->name;
602}
603
604/* Clear list of loaded DLLs. */
605void
606child_clear_solibs (void)
607{
608 struct so_stuff *so, *so1 = solib_start.next;
609
610 while ((so = so1) != NULL)
611 {
612 so1 = so->next;
613 free (so);
614 }
615
616 solib_start.next = NULL;
617 solib_end = &solib_start;
618 max_dll_name_len = sizeof ("DLL Name") - 1;
619}
620
621/* Add DLL symbol information. */
622void
9d3789f7 623child_solib_add (char *filename ATTRIBUTE_UNUSED, int from_tty ATTRIBUTE_UNUSED, struct target_ops *t ATTRIBUTE_UNUSED)
450005e7
CF
624{
625 struct section_addr_info section_addrs;
626
3cee93ac
CF
627 /* The symbols in a dll are offset by 0x1000, which is the
628 the offset from 0 of the first byte in an image - because
8a892701 629 of the file header and the section alignment. */
3cee93ac 630
450005e7
CF
631 if (!solib_end || !solib_end->name[0])
632 return;
633
634 memset (&section_addrs, 0, sizeof (section_addrs));
0aa9cf96 635 section_addrs.other[0].name = ".text";
450005e7
CF
636 section_addrs.other[0].addr = solib_end->load_addr;
637 safe_symbol_file_add (solib_end->name, 0, &section_addrs, 0, OBJF_SHARED);
3cee93ac 638
450005e7
CF
639 return;
640}
641
642/* Load DLL symbol info. */
643void
9d3789f7 644dll_symbol_command (char *args, int from_tty ATTRIBUTE_UNUSED)
450005e7 645{
450005e7
CF
646 dont_repeat ();
647
648 if (args == NULL)
649 error ("dll-symbols requires a file name");
650
9d3789f7 651 safe_symbol_file_add (args, 0, NULL, 0, OBJF_SHARED | OBJF_USERLOADED);
450005e7
CF
652}
653
654/* List currently loaded DLLs. */
655void
9d3789f7 656info_dll_command (char *ignore ATTRIBUTE_UNUSED, int from_tty ATTRIBUTE_UNUSED)
450005e7
CF
657{
658 struct so_stuff *so = &solib_start;
659
660 if (!so->next)
661 return;
662
663 printf ("%*s Load Address\n", -max_dll_name_len, "DLL Name");
664 while ((so = so->next) != NULL)
7c5c87c0 665 printf_filtered ("%*s %08lx\n", -max_dll_name_len, so->name, so->load_addr);
450005e7
CF
666
667 return;
24e60978
SC
668}
669
3cee93ac
CF
670/* Handle DEBUG_STRING output from child process.
671 Cygwin prepends its messages with a "cygwin:". Interpret this as
672 a Cygwin signal. Otherwise just print the string as a warning. */
673static int
674handle_output_debug_string (struct target_waitstatus *ourstatus)
675{
676 char *s;
677 int gotasig = FALSE;
678
679 if (!target_read_string
3a4b77d8 680 ((CORE_ADDR) current_event.u.DebugString.lpDebugStringData, &s, 1024, 0)
3cee93ac
CF
681 || !s || !*s)
682 return gotasig;
683
d3a09475 684 if (strncmp (s, CYGWIN_SIGNAL_STRING, sizeof (CYGWIN_SIGNAL_STRING) - 1) != 0)
3cee93ac 685 {
d3a09475 686 if (strncmp (s, "cYg", 3) != 0)
29fe111d 687 warning ("%s", s);
3cee93ac 688 }
d3a09475 689 else
3cee93ac
CF
690 {
691 char *p;
1e37c281
JM
692 int sig = strtol (s + sizeof (CYGWIN_SIGNAL_STRING) - 1, &p, 0);
693 gotasig = target_signal_from_host (sig);
0714f9bf
SS
694 ourstatus->value.sig = gotasig;
695 if (gotasig)
3cee93ac
CF
696 ourstatus->kind = TARGET_WAITKIND_STOPPED;
697 }
698
699 free (s);
700 return gotasig;
701}
24e60978 702
36339ecd 703static int
450005e7 704handle_exception (struct target_waitstatus *ourstatus)
24e60978 705{
3cee93ac 706 thread_info *th;
29fe111d 707 DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode;
3cee93ac 708
29fe111d 709 ourstatus->kind = TARGET_WAITKIND_STOPPED;
8a892701 710
3cee93ac
CF
711 /* Record the context of the current thread */
712 th = thread_rec (current_event.dwThreadId, -1);
24e60978 713
29fe111d 714 switch (code)
24e60978 715 {
1ef980b9 716 case EXCEPTION_ACCESS_VIOLATION:
29fe111d
CF
717 DEBUG_EXCEPT (("gdb: Target exception ACCESS_VIOLATION at 0x%08lx\n",
718 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1ef980b9 719 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
8a892701 720 last_sig = SIGSEGV;
1ef980b9 721 break;
3b7c8b74
JM
722 case STATUS_FLOAT_UNDERFLOW:
723 case STATUS_FLOAT_DIVIDE_BY_ZERO:
724 case STATUS_FLOAT_OVERFLOW:
725 case STATUS_INTEGER_DIVIDE_BY_ZERO:
29fe111d
CF
726 DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08lx\n",
727 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
3b7c8b74 728 ourstatus->value.sig = TARGET_SIGNAL_FPE;
29fe111d 729 last_sig = SIGFPE;
3b7c8b74 730 break;
1ef980b9 731 case STATUS_STACK_OVERFLOW:
29fe111d
CF
732 DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08lx\n",
733 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1ef980b9
SC
734 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
735 break;
736 case EXCEPTION_BREAKPOINT:
29fe111d
CF
737 DEBUG_EXCEPT (("gdb: Target exception BREAKPOINT at 0x%08lx\n",
738 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1ef980b9
SC
739 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
740 break;
741 case DBG_CONTROL_C:
29fe111d
CF
742 DEBUG_EXCEPT (("gdb: Target exception CONTROL_C at 0x%08lx\n",
743 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1ef980b9 744 ourstatus->value.sig = TARGET_SIGNAL_INT;
8a892701 745 last_sig = SIGINT; /* FIXME - should check pass state */
1ef980b9
SC
746 break;
747 case EXCEPTION_SINGLE_STEP:
29fe111d
CF
748 DEBUG_EXCEPT (("gdb: Target exception SINGLE_STEP at 0x%08lx\n",
749 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1ef980b9
SC
750 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
751 break;
8227c82d 752 case EXCEPTION_ILLEGAL_INSTRUCTION:
29fe111d
CF
753 DEBUG_EXCEPT (("gdb: Target exception SINGLE_ILL at 0x%08lx\n",
754 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
8227c82d 755 ourstatus->value.sig = TARGET_SIGNAL_ILL;
8a892701 756 last_sig = SIGILL;
8227c82d 757 break;
1ef980b9 758 default:
29fe111d 759 printf_unfiltered ("gdb: unknown target exception 0x%08lx at 0x%08lx\n",
3a4b77d8 760 current_event.u.Exception.ExceptionRecord.ExceptionCode,
29fe111d 761 (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress);
24e60978 762 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
1ef980b9 763 break;
24e60978 764 }
24e60978 765 exception_count++;
36339ecd 766 return 1;
24e60978
SC
767}
768
3cee93ac
CF
769/* Resume all artificially suspended threads if we are continuing
770 execution */
771static BOOL
8a892701 772child_continue (DWORD continue_status, int id)
3cee93ac
CF
773{
774 int i;
775 thread_info *th;
776 BOOL res;
777
29fe111d 778 DEBUG_EVENTS (("ContinueDebugEvent (cpid=%ld, ctid=%ld, DBG_CONTINUE);\n",
3cee93ac 779 current_event.dwProcessId, current_event.dwThreadId));
0714f9bf
SS
780 res = ContinueDebugEvent (current_event.dwProcessId,
781 current_event.dwThreadId,
782 continue_status);
1e37c281 783 continue_status = 0;
0714f9bf 784 if (res)
3a4b77d8 785 for (th = &thread_head; (th = th->next) != NULL;)
29fe111d 786 if (((id == -1) || (id == (int) th->id)) && th->suspend_count)
3cee93ac
CF
787 {
788 for (i = 0; i < th->suspend_count; i++)
789 (void) ResumeThread (th->h);
790 th->suspend_count = 0;
791 }
792
793 return res;
794}
795
8a892701
CF
796/* Get the next event from the child. Return 1 if the event requires
797 handling by WFI (or whatever).
798 */
1e37c281 799static int
450005e7 800get_child_debug_event (int pid ATTRIBUTE_UNUSED, struct target_waitstatus *ourstatus)
1e37c281
JM
801{
802 BOOL debug_event;
8a892701
CF
803 DWORD continue_status, event_code;
804 thread_info *th = NULL;
805 static thread_info dummy_thread_info;
450005e7 806 int retval = 0;
1e37c281 807
9d3789f7
CF
808 last_sig = 0;
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
9d3789f7 851 main_thread_id = current_event.dwThreadId;
1e37c281 852 /* Add the main thread */
9d3789f7 853#if 0
450005e7
CF
854 th = child_add_thread (current_event.dwProcessId,
855 current_event.u.CreateProcessInfo.hProcess);
9d3789f7
CF
856#endif
857 th = child_add_thread (main_thread_id,
8a892701 858 current_event.u.CreateProcessInfo.hThread);
9d3789f7 859 retval = ourstatus->value.related_pid = current_event.dwThreadId;
1e37c281
JM
860 break;
861
862 case EXIT_PROCESS_DEBUG_EVENT:
863 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
864 (unsigned) current_event.dwProcessId,
865 (unsigned) current_event.dwThreadId,
866 "EXIT_PROCESS_DEBUG_EVENT"));
1e37c281
JM
867 ourstatus->kind = TARGET_WAITKIND_EXITED;
868 ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
869 CloseHandle (current_process_handle);
9d3789f7 870 retval = main_thread_id;
8a892701 871 break;
1e37c281
JM
872
873 case LOAD_DLL_DEBUG_EVENT:
874 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
875 (unsigned) current_event.dwProcessId,
876 (unsigned) current_event.dwThreadId,
877 "LOAD_DLL_DEBUG_EVENT"));
878 catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL);
1e37c281 879 registers_changed (); /* mark all regs invalid */
450005e7
CF
880 ourstatus->kind = TARGET_WAITKIND_LOADED;
881 ourstatus->value.integer = 0;
9d3789f7 882 retval = main_thread_id;
1e37c281
JM
883 break;
884
885 case UNLOAD_DLL_DEBUG_EVENT:
886 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
887 (unsigned) current_event.dwProcessId,
888 (unsigned) current_event.dwThreadId,
889 "UNLOAD_DLL_DEBUG_EVENT"));
890 break; /* FIXME: don't know what to do here */
1e37c281
JM
891
892 case EXCEPTION_DEBUG_EVENT:
893 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
894 (unsigned) current_event.dwProcessId,
895 (unsigned) current_event.dwThreadId,
896 "EXCEPTION_DEBUG_EVENT"));
450005e7
CF
897 handle_exception (ourstatus);
898 retval = current_event.dwThreadId;
1e37c281
JM
899 break;
900
8a892701 901 case OUTPUT_DEBUG_STRING_EVENT: /* message from the kernel */
1e37c281 902 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
8a892701
CF
903 (unsigned) current_event.dwProcessId,
904 (unsigned) current_event.dwThreadId,
905 "OUTPUT_DEBUG_STRING_EVENT"));
450005e7 906 if (handle_output_debug_string ( ourstatus))
9d3789f7 907 retval = main_thread_id;
1e37c281 908 break;
9d3789f7 909
1e37c281 910 default:
29fe111d
CF
911 printf_unfiltered ("gdb: kernel event for pid=%ld tid=%ld\n",
912 (DWORD) current_event.dwProcessId,
913 (DWORD) current_event.dwThreadId);
914 printf_unfiltered (" unknown event code %ld\n",
1e37c281
JM
915 current_event.dwDebugEventCode);
916 break;
917 }
918
450005e7 919 if (!retval)
8a892701 920 CHECK (child_continue (continue_status, -1));
450005e7 921 else
9d3789f7
CF
922 {
923 current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
924 inferior_pid = retval;
925 }
1e37c281
JM
926
927out:
450005e7 928 return retval;
1e37c281
JM
929}
930
1e37c281 931/* Wait for interesting events to occur in the target process. */
24e60978
SC
932static int
933child_wait (int pid, struct target_waitstatus *ourstatus)
934{
935 /* We loop when we get a non-standard exception rather than return
936 with a SPURIOUS because resume can try and step or modify things,
3cee93ac 937 which needs a current_thread->h. But some of these exceptions mark
24e60978
SC
938 the birth or death of threads, which mean that the current thread
939 isn't necessarily what you think it is. */
940
941 while (1)
450005e7
CF
942 {
943 int retval = get_child_debug_event (pid, ourstatus);
944 if (retval)
945 return retval;
946 else
947 {
948 int detach = 0;
3cee93ac 949
450005e7
CF
950 if (ui_loop_hook != NULL)
951 detach = ui_loop_hook (0);
0714f9bf 952
450005e7
CF
953 if (detach)
954 child_kill_inferior ();
955 }
956 }
24e60978
SC
957}
958
9d3789f7
CF
959static void
960do_initial_child_stuff (DWORD pid)
961{
962 extern int stop_after_trap;
963
964 last_sig = 0;
965 event_count = 0;
966 exception_count = 0;
967 current_event.dwProcessId = pid;
968 memset (&current_event, 0, sizeof (current_event));
969 push_target (&child_ops);
970 child_init_thread_list ();
971 child_clear_solibs ();
972 clear_proceed_status ();
973 init_wait_for_inferior ();
974
975 target_terminal_init ();
976 target_terminal_inferior ();
977
978 while (1)
979 {
980 stop_after_trap = 1;
981 wait_for_inferior ();
982 if (stop_signal != TARGET_SIGNAL_TRAP)
983 resume (0, stop_signal);
984 else
985 break;
986 }
987 stop_after_trap = 0;
988 return;
989}
990
24e60978
SC
991/* Attach to process PID, then initialize for debugging it. */
992
993static void
fba45db2 994child_attach (char *args, int from_tty)
24e60978
SC
995{
996 BOOL ok;
9d3789f7 997 DWORD pid = strtoul (args, 0, 0);
24e60978
SC
998
999 if (!args)
1000 error_no_arg ("process-id to attach");
1001
9d3789f7 1002 ok = DebugActiveProcess (pid);
24e60978
SC
1003
1004 if (!ok)
1005 error ("Can't attach to process.");
1006
24e60978
SC
1007 if (from_tty)
1008 {
1009 char *exec_file = (char *) get_exec_file (0);
1010
1011 if (exec_file)
1012 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
9d3789f7 1013 target_pid_to_str (pid));
24e60978
SC
1014 else
1015 printf_unfiltered ("Attaching to %s\n",
9d3789f7 1016 target_pid_to_str (pid));
24e60978
SC
1017
1018 gdb_flush (gdb_stdout);
1019 }
1020
9d3789f7
CF
1021 do_initial_child_stuff (pid);
1022 target_terminal_ours ();
24e60978
SC
1023}
1024
24e60978 1025static void
29fe111d 1026child_detach (char *args ATTRIBUTE_UNUSED, int from_tty)
24e60978
SC
1027{
1028 if (from_tty)
1029 {
1030 char *exec_file = get_exec_file (0);
1031 if (exec_file == 0)
1032 exec_file = "";
1033 printf_unfiltered ("Detaching from program: %s %s\n", exec_file,
1034 target_pid_to_str (inferior_pid));
1035 gdb_flush (gdb_stdout);
1036 }
1037 inferior_pid = 0;
1038 unpush_target (&child_ops);
1039}
1040
24e60978
SC
1041/* Print status information about what we're accessing. */
1042
1043static void
29fe111d 1044child_files_info (struct target_ops *ignore ATTRIBUTE_UNUSED)
24e60978
SC
1045{
1046 printf_unfiltered ("\tUsing the running image of %s %s.\n",
1047 attach_flag ? "attached" : "child", target_pid_to_str (inferior_pid));
1048}
1049
1050/* ARGSUSED */
1051static void
29fe111d 1052child_open (char *arg ATTRIBUTE_UNUSED, int from_tty ATTRIBUTE_UNUSED)
24e60978
SC
1053{
1054 error ("Use the \"run\" command to start a Unix child process.");
1055}
1056
eb708f2e 1057/* Start an inferior win32 child process and sets inferior_pid to its pid.
24e60978
SC
1058 EXEC_FILE is the file to run.
1059 ALLARGS is a string containing the arguments to the program.
1060 ENV is the environment vector to pass. Errors reported with error(). */
1061
24e60978 1062static void
fba45db2 1063child_create_inferior (char *exec_file, char *allargs, char **env)
24e60978 1064{
1750a5ef
SC
1065 char real_path[MAXPATHLEN];
1066 char *winenv;
1067 char *temp;
3a4b77d8 1068 int envlen;
1750a5ef 1069 int i;
24e60978
SC
1070 STARTUPINFO si;
1071 PROCESS_INFORMATION pi;
24e60978
SC
1072 BOOL ret;
1073 DWORD flags;
eb708f2e 1074 char *args;
24e60978
SC
1075
1076 if (!exec_file)
450005e7 1077 error ("No executable specified, use `target exec'.\n");
24e60978
SC
1078
1079 memset (&si, 0, sizeof (si));
1080 si.cb = sizeof (si);
1081
29fe111d 1082 cygwin_conv_to_win32_path (exec_file, real_path);
24e60978 1083
3cee93ac 1084 flags = DEBUG_ONLY_THIS_PROCESS;
24e60978
SC
1085
1086 if (new_group)
1087 flags |= CREATE_NEW_PROCESS_GROUP;
1088
1089 if (new_console)
1090 flags |= CREATE_NEW_CONSOLE;
1091
3d78f532
SC
1092 args = alloca (strlen (real_path) + strlen (allargs) + 2);
1093
1094 strcpy (args, real_path);
eb708f2e 1095
eb708f2e
SC
1096 strcat (args, " ");
1097 strcat (args, allargs);
1098
e88c49c3
DE
1099 /* Prepare the environment vars for CreateProcess. */
1100 {
1101 /* This code use to assume all env vars were file names and would
1102 translate them all to win32 style. That obviously doesn't work in the
2dcfc9c7
DE
1103 general case. The current rule is that we only translate PATH.
1104 We need to handle PATH because we're about to call CreateProcess and
1105 it uses PATH to find DLL's. Fortunately PATH has a well-defined value
1106 in both posix and win32 environments. cygwin.dll will change it back
1107 to posix style if necessary. */
e88c49c3
DE
1108
1109 static const char *conv_path_names[] =
3a4b77d8
JM
1110 {
1111 "PATH=",
1112 0
1113 };
e88c49c3
DE
1114
1115 /* CreateProcess takes the environment list as a null terminated set of
1116 strings (i.e. two nulls terminate the list). */
1117
1118 /* Get total size for env strings. */
1119 for (envlen = 0, i = 0; env[i] && *env[i]; i++)
1120 {
2dcfc9c7 1121 int j, len;
e88c49c3 1122
2dcfc9c7
DE
1123 for (j = 0; conv_path_names[j]; j++)
1124 {
1125 len = strlen (conv_path_names[j]);
1126 if (strncmp (conv_path_names[j], env[i], len) == 0)
e88c49c3 1127 {
29fe111d 1128 if (cygwin_posix_path_list_p (env[i] + len))
2dcfc9c7 1129 envlen += len
29fe111d 1130 + cygwin_posix_to_win32_path_list_buf_size (env[i] + len);
2dcfc9c7
DE
1131 else
1132 envlen += strlen (env[i]) + 1;
1133 break;
e88c49c3 1134 }
e88c49c3 1135 }
2dcfc9c7 1136 if (conv_path_names[j] == NULL)
e88c49c3
DE
1137 envlen += strlen (env[i]) + 1;
1138 }
1139
1140 winenv = alloca (envlen + 1);
1141
1142 /* Copy env strings into new buffer. */
3cee93ac 1143 for (temp = winenv, i = 0; env[i] && *env[i]; i++)
e88c49c3 1144 {
2dcfc9c7 1145 int j, len;
e88c49c3 1146
2dcfc9c7
DE
1147 for (j = 0; conv_path_names[j]; j++)
1148 {
1149 len = strlen (conv_path_names[j]);
1150 if (strncmp (conv_path_names[j], env[i], len) == 0)
e88c49c3 1151 {
29fe111d 1152 if (cygwin_posix_path_list_p (env[i] + len))
e88c49c3
DE
1153 {
1154 memcpy (temp, env[i], len);
29fe111d 1155 cygwin_posix_to_win32_path_list (env[i] + len, temp + len);
e88c49c3 1156 }
2dcfc9c7
DE
1157 else
1158 strcpy (temp, env[i]);
1159 break;
e88c49c3 1160 }
e88c49c3 1161 }
2dcfc9c7 1162 if (conv_path_names[j] == NULL)
e88c49c3 1163 strcpy (temp, env[i]);
2dcfc9c7 1164
e88c49c3
DE
1165 temp += strlen (temp) + 1;
1166 }
1167
1168 /* Final nil string to terminate new env. */
1169 *temp = 0;
1170 }
1750a5ef 1171
1750a5ef 1172 ret = CreateProcess (0,
3a4b77d8 1173 args, /* command line */
24e60978
SC
1174 NULL, /* Security */
1175 NULL, /* thread */
1176 TRUE, /* inherit handles */
1177 flags, /* start flags */
1750a5ef 1178 winenv,
24e60978
SC
1179 NULL, /* current directory */
1180 &si,
1181 &pi);
1182 if (!ret)
3a4b77d8 1183 error ("Error creating process %s, (error %d)\n", exec_file, GetLastError ());
24e60978 1184
9d3789f7 1185 do_initial_child_stuff (pi.dwProcessId);
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
fba45db2 1192child_mourn_inferior (void)
24e60978 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
fba45db2 1203child_stop (void)
24e60978 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
fba45db2 1292child_prepare_to_store (void)
24e60978
SC
1293{
1294 /* Do nothing, since we can store individual regs */
1295}
1296
1297static int
fba45db2 1298child_can_run (void)
24e60978
SC
1299{
1300 return 1;
1301}
1302
1303static void
9d3789f7 1304child_close (int x ATTRIBUTE_UNUSED)
24e60978 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
fba45db2 1358_initialize_inftarg (void)
24e60978 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.315684 seconds and 4 git commands to generate.