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