OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [win32-nat.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.