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