* MAINTAINERS: Add Alfred Szmidt for the Hurd.
[platform/upstream/binutils.git] / gdb / wince.c
1 /* Target-vector operations for controlling Windows CE child processes, for GDB.
2
3    Copyright (C) 1999, 2000, 2001, 2004, 2006 Free Software Foundation, Inc.
4    Contributed by Cygnus Solutions, A Red Hat Company.
5
6    This file is part of GDB.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor,
21    Boston, MA 02110-1301, USA.
22  */
23
24 /* by Christopher Faylor (cgf@cygnus.com) */
25
26 /* We assume we're being built with and will be used for cygwin.  */
27
28 #ifdef SHx
29 #undef SH4
30 #define SH4             /* Just to get all of the CONTEXT defines.  */
31 #endif
32
33 #include "defs.h"
34 #include "frame.h"      /* required by inferior.h */
35 #include "inferior.h"
36 #include "target.h"
37 #include "exceptions.h"
38 #include "gdbcore.h"
39 #include "command.h"
40 #include <signal.h>
41 #include <sys/types.h>
42 #include <fcntl.h>
43 #include <stdlib.h>
44
45 #include <windows.h>
46 #include <rapi.h>
47 #include <netdb.h>
48 #include <cygwin/in.h>
49 #include <cygwin/socket.h>
50
51 #include "buildsym.h"
52 #include "symfile.h"
53 #include "objfiles.h"
54 #include "gdb_string.h"
55 #include "gdbthread.h"
56 #include "gdbcmd.h"
57 #include <sys/param.h>
58 #include "wince-stub.h"
59 #include <time.h>
60 #include "regcache.h"
61 #ifdef MIPS
62 #include "mips-tdep.h"
63 #endif
64
65 /* If we're not using the old Cygwin header file set, define the
66    following which never should have been in the generic Win32 API
67    headers in the first place since they were our own invention...  */
68 #ifndef _GNU_H_WINDOWS_H
69 #define FLAG_TRACE_BIT 0x100
70 #ifdef CONTEXT_FLOATING_POINT
71 #define CONTEXT_DEBUGGER0 (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
72 #else
73 #define CONTEXT_DEBUGGER0 (CONTEXT_FULL)
74 #endif
75 #endif
76
77 #ifdef SH4
78 #define CONTEXT_DEBUGGER ((CONTEXT_DEBUGGER0 & ~(CONTEXT_SH4 | CONTEXT_FLOATING_POINT)) | CONTEXT_SH3)
79 #else
80 #define CONTEXT_DEBUGGER CONTEXT_DEBUGGER0
81 #endif
82 /* The string sent by cygwin when it processes a signal.
83    FIXME: This should be in a cygwin include file.  */
84 #define CYGWIN_SIGNAL_STRING "cygwin: signal"
85
86 #define CHECK(x)        check (x, __FILE__,__LINE__)
87 #define DEBUG_EXEC(x)   if (debug_exec)         printf x
88 #define DEBUG_EVENTS(x) if (debug_events)       printf x
89 #define DEBUG_MEM(x)    if (debug_memory)       printf x
90 #define DEBUG_EXCEPT(x) if (debug_exceptions)   printf x
91
92 static int connection_initialized = 0;  /* True if we've initialized a
93                                            RAPI session.  */
94
95 /* The directory where the stub and executable files are uploaded.  */
96 static const char *remote_directory = "\\gdb";
97
98 /* The types automatic upload available.  */
99 static enum
100   {
101     UPLOAD_ALWAYS = 0,
102     UPLOAD_NEWER = 1,
103     UPLOAD_NEVER = 2
104   }
105 upload_when = UPLOAD_NEWER;
106
107 /* Valid options for 'set remoteupload'.  Note that options
108    must track upload_when enum.  */
109 static struct opts
110   {
111     const char *name;
112     int abbrev;
113   }
114 upload_options[3] =
115 {
116   {
117     "always", 1
118   }
119   ,
120   {
121     "newer", 3
122   }
123   ,
124   {
125     "never", 3
126   }
127 };
128
129 static char *remote_upload = NULL;      /* Set by set remoteupload.  */
130 static int remote_add_host = 0;
131
132 static int win32_child_thread_alive (ptid_t);
133 void child_kill_inferior (void);
134
135 static int last_sig = 0;        /* Set if a signal was received from
136                                    the debugged process.  */
137
138 /* Thread information structure used to track information that is
139    not available in gdb's thread structure.  */
140 typedef struct thread_info_struct
141   {
142     struct thread_info_struct *next;
143     DWORD id;
144     HANDLE h;
145     char *name;
146     int suspend_count;
147     int stepped;                /* True if stepped.  */
148     CORE_ADDR step_pc;
149     CONTEXT context;
150   }
151 thread_info;
152
153 static thread_info thread_head =
154 {NULL};
155 static thread_info * thread_rec (DWORD id, int get_context);
156
157 /* The process and thread handles for the above context.  */
158
159 static DEBUG_EVENT current_event;       /* The current debug event from
160                                            WaitForDebugEvent.  */
161 static HANDLE current_process_handle;   /* Currently executing process.  */
162 static thread_info *current_thread;     /* Info on currently selected
163                                            thread.  */
164 static thread_info *this_thread;        /* Info on thread returned by
165                                            wait_for_debug_event.  */
166 static DWORD main_thread_id;            /* Thread ID of the main thread.  */
167
168 /* Counts of things.  */
169 static int exception_count = 0;
170 static int event_count = 0;
171
172 /* User options.  */
173 static int debug_exec = 0;              /* show execution */
174 static int debug_events = 0;            /* show events from kernel */
175 static int debug_memory = 0;            /* show target memory accesses */
176 static int debug_exceptions = 0;        /* show target exceptions */
177
178 /* An array of offset mappings into a Win32 Context structure.
179    This is a one-to-one mapping which is indexed by gdb's register
180    numbers.  It retrieves an offset into the context structure where
181    the 4 byte register is located.
182    An offset value of -1 indicates that Win32 does not provide this
183    register in it's CONTEXT structure.  regptr will return zero for this
184    register.
185
186    This is used by the regptr function.  */
187 #define context_offset(x) ((int)&(((PCONTEXT)NULL)->x))
188 static const int mappings[NUM_REGS + 1] =
189 {
190 #ifdef __i386__
191   context_offset (Eax),
192   context_offset (Ecx),
193   context_offset (Edx),
194   context_offset (Ebx),
195   context_offset (Esp),
196   context_offset (Ebp),
197   context_offset (Esi),
198   context_offset (Edi),
199   context_offset (Eip),
200   context_offset (EFlags),
201   context_offset (SegCs),
202   context_offset (SegSs),
203   context_offset (SegDs),
204   context_offset (SegEs),
205   context_offset (SegFs),
206   context_offset (SegGs),
207   context_offset (FloatSave.RegisterArea[0 * 10]),
208   context_offset (FloatSave.RegisterArea[1 * 10]),
209   context_offset (FloatSave.RegisterArea[2 * 10]),
210   context_offset (FloatSave.RegisterArea[3 * 10]),
211   context_offset (FloatSave.RegisterArea[4 * 10]),
212   context_offset (FloatSave.RegisterArea[5 * 10]),
213   context_offset (FloatSave.RegisterArea[6 * 10]),
214   context_offset (FloatSave.RegisterArea[7 * 10]),
215 #elif defined(SHx)
216   context_offset (R0),
217   context_offset (R1),
218   context_offset (R2),
219   context_offset (R3),
220   context_offset (R4),
221   context_offset (R5),
222   context_offset (R6),
223   context_offset (R7),
224   context_offset (R8),
225   context_offset (R9),
226   context_offset (R10),
227   context_offset (R11),
228   context_offset (R12),
229   context_offset (R13),
230   context_offset (R14),
231   context_offset (R15),
232   context_offset (Fir),
233   context_offset (PR),          /* Procedure Register */
234   context_offset (GBR),         /* Global Base Register */
235   context_offset (MACH),        /* Accumulate */
236   context_offset (MACL),        /* Multiply */
237   context_offset (Psr),
238   context_offset (Fpul),
239   context_offset (Fpscr),
240   context_offset (FRegs[0]),
241   context_offset (FRegs[1]),
242   context_offset (FRegs[2]),
243   context_offset (FRegs[3]),
244   context_offset (FRegs[4]),
245   context_offset (FRegs[5]),
246   context_offset (FRegs[6]),
247   context_offset (FRegs[7]),
248   context_offset (FRegs[8]),
249   context_offset (FRegs[9]),
250   context_offset (FRegs[10]),
251   context_offset (FRegs[11]),
252   context_offset (FRegs[12]),
253   context_offset (FRegs[13]),
254   context_offset (FRegs[14]),
255   context_offset (FRegs[15]),
256   context_offset (xFRegs[0]),
257   context_offset (xFRegs[1]),
258   context_offset (xFRegs[2]),
259   context_offset (xFRegs[3]),
260   context_offset (xFRegs[4]),
261   context_offset (xFRegs[5]),
262   context_offset (xFRegs[6]),
263   context_offset (xFRegs[7]),
264   context_offset (xFRegs[8]),
265   context_offset (xFRegs[9]),
266   context_offset (xFRegs[10]),
267   context_offset (xFRegs[11]),
268   context_offset (xFRegs[12]),
269   context_offset (xFRegs[13]),
270   context_offset (xFRegs[14]),
271   context_offset (xFRegs[15]),
272 #elif defined(MIPS)
273   context_offset (IntZero),
274   context_offset (IntAt),
275   context_offset (IntV0),
276   context_offset (IntV1),
277   context_offset (IntA0),
278   context_offset (IntA1),
279   context_offset (IntA2),
280   context_offset (IntA3),
281   context_offset (IntT0),
282   context_offset (IntT1),
283   context_offset (IntT2),
284   context_offset (IntT3),
285   context_offset (IntT4),
286   context_offset (IntT5),
287   context_offset (IntT6),
288   context_offset (IntT7),
289   context_offset (IntS0),
290   context_offset (IntS1),
291   context_offset (IntS2),
292   context_offset (IntS3),
293   context_offset (IntS4),
294   context_offset (IntS5),
295   context_offset (IntS6),
296   context_offset (IntS7),
297   context_offset (IntT8),
298   context_offset (IntT9),
299   context_offset (IntK0),
300   context_offset (IntK1),
301   context_offset (IntGp),
302   context_offset (IntSp),
303   context_offset (IntS8),
304   context_offset (IntRa),
305   context_offset (Psr),
306   context_offset (IntLo),
307   context_offset (IntHi),
308   -1,                           /* bad */
309   -1,                           /* cause */
310   context_offset (Fir),
311   context_offset (FltF0),
312   context_offset (FltF1),
313   context_offset (FltF2),
314   context_offset (FltF3),
315   context_offset (FltF4),
316   context_offset (FltF5),
317   context_offset (FltF6),
318   context_offset (FltF7),
319   context_offset (FltF8),
320   context_offset (FltF9),
321   context_offset (FltF10),
322   context_offset (FltF11),
323   context_offset (FltF12),
324   context_offset (FltF13),
325   context_offset (FltF14),
326   context_offset (FltF15),
327   context_offset (FltF16),
328   context_offset (FltF17),
329   context_offset (FltF18),
330   context_offset (FltF19),
331   context_offset (FltF20),
332   context_offset (FltF21),
333   context_offset (FltF22),
334   context_offset (FltF23),
335   context_offset (FltF24),
336   context_offset (FltF25),
337   context_offset (FltF26),
338   context_offset (FltF27),
339   context_offset (FltF28),
340   context_offset (FltF29),
341   context_offset (FltF30),
342   context_offset (FltF31),
343   context_offset (Fsr),
344   context_offset (Fir),
345   -1,                           /* fp */
346 #elif defined(ARM)
347   context_offset (R0),
348   context_offset (R1),
349   context_offset (R2),
350   context_offset (R3),
351   context_offset (R4),
352   context_offset (R5),
353   context_offset (R6),
354   context_offset (R7),
355   context_offset (R8),
356   context_offset (R9),
357   context_offset (R10),
358   context_offset (R11),
359   context_offset (R12),
360   context_offset (Sp),
361   context_offset (Lr),
362   context_offset (Pc),
363   -1,
364   -1,
365   -1,
366   -1,
367   -1,
368   -1,
369   -1,
370   -1,
371   -1,
372   context_offset (Psr),
373 #endif
374   -1
375 };
376
377 /* Return a pointer into a CONTEXT field indexed by gdb register number.
378    Return a pointer to an address pointing to zero if there is no
379    corresponding CONTEXT field for the given register number.
380  */
381 static ULONG *
382 regptr (LPCONTEXT c, int r)
383 {
384   static ULONG zero = 0;
385   ULONG *p;
386   if (mappings[r] < 0)
387     p = &zero;
388   else
389     p = (ULONG *) (((char *) c) + mappings[r]);
390   return p;
391 }
392
393 /******************** Beginning of stub interface ********************/
394
395 /* Stub interface description:
396
397    The Windows CE stub implements a crude RPC.  The hand-held device
398    connects to gdb using port 7000.  gdb and the stub then communicate
399    using packets where:
400
401    byte 0:              command id (e.g. Create Process)
402
403    byte 1-4:    DWORD
404
405    byte 1-2:    WORD
406
407    byte 1-2:    length
408    byte 3-n:    arbitrary memory.
409
410    The interface is deterministic, i.e., if the stub expects a DWORD
411    then the gdb server should send a DWORD.
412  */
413
414 /* Note: In the functions below, the `huh' parameter is a string
415    passed from the function containing a descriptive string concerning
416    the current operation.  This is used for error reporting.
417
418    The 'what' parameter is a command id as found in wince-stub.h.
419
420    Hopefully, the rest of the parameters are self-explanatory.
421  */
422
423 static int s;                   /* communication socket */
424
425 /* v-style interface for handling varying argyment list error messages.
426    Displays the error message in a dialog box and exits when user clicks
427    on OK.  */
428 static void
429 vstub_error (LPCSTR fmt, va_list * args)
430 {
431   char buf[4096];
432   vsprintf (buf, fmt, args);
433   s = -1;
434   error (("%s"), buf);
435 }
436
437 /* The standard way to display an error message and exit.  */
438 static void
439 stub_error (LPCSTR fmt,...)
440 {
441   va_list args;
442   va_start (args, fmt);
443   vstub_error (fmt, args);
444 }
445
446 /* Standard "oh well" can't communicate error.  Someday this might
447    attempt synchronization.  */
448 static void
449 attempt_resync (LPCSTR huh, int s)
450 {
451   stub_error ("lost synchronization with target attempting %s", huh);
452 }
453
454 /* Read arbitrary stuff from a socket.  */
455 static int
456 sockread (LPCSTR huh, int s, void *str, size_t n)
457 {
458   for (;;)
459     {
460       if (recv (s, str, n, 0) == n)
461         return n;
462       attempt_resync (huh, s);
463     }
464 }
465
466 /* Write arbitrary stuff to a socket.  */
467 static int
468 sockwrite (LPCSTR huh, const void *str, size_t n)
469 {
470   for (;;)
471     {
472       if (send (s, str, n, 0) == n)
473         return n;
474       attempt_resync (huh, s);
475     }
476 }
477
478 /* Output an id/dword to the host.  */
479 static void
480 putdword (LPCSTR huh, gdb_wince_id what, DWORD n)
481 {
482   if (sockwrite (huh, &what, sizeof (what)) != sizeof (what))
483     stub_error ("error writing record id to host for %s", huh);
484   if (sockwrite (huh, &n, sizeof (n)) != sizeof (n))
485     stub_error ("error writing %s to host.", huh);
486 }
487
488 /* Output an id/word to the host.  */
489 static void
490 putword (LPCSTR huh, gdb_wince_id what, WORD n)
491 {
492   if (sockwrite (huh, &what, sizeof (what)) != sizeof (what))
493     stub_error ("error writing record id to host for %s", huh);
494   if (sockwrite (huh, &n, sizeof (n)) != sizeof (n))
495     stub_error ("error writing %s host.", huh);
496 }
497
498 /* Convenience define for outputting a "gdb_wince_len" type.  */
499 #define putlen(huh, what, n) putword((huh), (what), (gdb_wince_len) (n))
500
501 /* Put an arbitrary block of memory to the gdb host.  This comes in
502    two chunks an id/dword representing the length and the stream of
503    memory itself.  */
504 static void
505 putmemory (LPCSTR huh, gdb_wince_id what, 
506            const void *mem, gdb_wince_len len)
507 {
508   putlen (huh, what, len);
509   if (((short) len > 0) && sockwrite (huh, mem, len) != len)
510     stub_error ("error writing %s to host.", huh);
511 }
512
513 /* Output the result of an operation to the host.  If res != 0, sends
514    a block of memory starting at mem of len bytes.  If res == 0, sends
515    -GetLastError () and avoids sending the mem.  */
516 static DWORD
517 getdword (LPCSTR huh, gdb_wince_id what_this)
518 {
519   DWORD n;
520   gdb_wince_id what;
521   do
522     if (sockread (huh, s, &what, sizeof (what)) != sizeof (what))
523       stub_error ("error getting record type from host - %s.", huh);
524   while (what_this != what);
525
526   if (sockread (huh, s, &n, sizeof (n)) != sizeof (n))
527     stub_error ("error getting %s from host.", huh);
528
529   return n;
530 }
531
532 /* Get a an ID (possibly) and a WORD from the host gdb.
533    Don't bother with the id if the main loop has already
534    read it.  */
535 static WORD
536 getword (LPCSTR huh, gdb_wince_id what_this)
537 {
538   WORD n;
539   gdb_wince_id what;
540   do
541     if (sockread (huh, s, &what, sizeof (what)) != sizeof (what))
542       stub_error ("error getting record type from host - %s.", huh);
543   while (what_this != what);
544
545   if (sockread (huh, s, &n, sizeof (n)) != sizeof (n))
546     stub_error ("error getting %s from host.", huh);
547
548   return n;
549 }
550
551 /* Handy defines for getting/putting various types of values.  */
552 #define gethandle(huh, what) (HANDLE) getdword ((huh), (what))
553 #define getpvoid(huh, what) (LPVOID) getdword ((huh), (what))
554 #define getlen(huh, what) (gdb_wince_len) getword ((huh), (what))
555 #define puthandle(huh, what, h) putdword ((huh), (what), (DWORD) (h))
556 #define putpvoid(huh, what, p) putdword ((huh), (what), (DWORD) (p))
557
558 /* Retrieve the result of an operation from the stub.  If nbytes < 0)
559    then nbytes is actually an error and nothing else follows.  Use
560    SetLastError to remember this.  if nbytes > 0, retrieve a block of
561    *nbytes into buf.
562  */
563 int
564 getresult (LPCSTR huh, gdb_wince_id what, LPVOID buf, 
565            gdb_wince_len * nbytes)
566 {
567   gdb_wince_len dummy;
568   if (nbytes == NULL)
569     nbytes = &dummy;
570
571   *nbytes = getlen (huh, what);
572
573   if ((short) *nbytes < 0)
574     {
575       SetLastError (-(short) *nbytes);
576       return 0;
577     }
578
579   if ((gdb_wince_len) sockread (huh, s, buf, *nbytes) != *nbytes)
580     stub_error ("couldn't read information from wince stub - %s", huh);
581
582   return 1;
583 }
584
585 /* Convert "narrow" string to "wide".  Manipulates a buffer ring of 8
586    buffers which hold the translated string.  This is an arbitrary limit
587    but it is approximately double the current needs of this module.
588  */
589 LPWSTR
590 towide (const char *s, gdb_wince_len * out_len)
591 {
592   static int n = -1;
593   static LPWSTR outs[8] =
594   {NULL /*, NULL, etc.  */ };
595   gdb_wince_len dummy;
596
597   if (!out_len)
598     out_len = &dummy;
599
600   /* First determine the length required to hold the converted string.  */
601   *out_len = sizeof (WCHAR) * MultiByteToWideChar (CP_ACP, 0, s, 
602                                                    -1, NULL, 0);
603   if (!*out_len)
604     return NULL;                /* The conversion failed.  */
605
606   if (++n >= (sizeof (outs) / sizeof (outs[0])))
607     n = 0;                      /* wrap */
608
609   /* Allocate space for the converted string, reusing any previously
610      allocated space, if applicable. Note that if outs[n] is NULL,
611      xrealloc will act as a malloc (under cygwin, at least).
612    */
613   outs[n] = (LPWSTR) xrealloc (outs[n], *out_len);
614   memset (outs[n], 0, *out_len);
615   (void) MultiByteToWideChar (CP_ACP, 0, s, -1, outs[n], *out_len);
616   return outs[n];
617 }
618
619 /******************** Emulation routines start here. ********************
620
621   The functions below are modelled after their Win32 counterparts.
622   They are named similarly to Win32 and take exactly the same
623   arguments except where otherwise noted.  They communicate with the
624   stub on the hand-held device by sending their arguments over the
625   socket and waiting for results from the socket.
626
627   There is one universal change.  In cases where a length is expected
628   to be returned in a DWORD, we use a gdb_wince_len type instead.
629   Currently this is an unsigned short which is smaller than the
630   standard Win32 DWORD.  This is done to minimize unnecessary traffic
631   since the connection to Windows CE can be slow.  To change this,
632   modify the typedef in wince-stub.h and change the putlen/getlen
633   macros in this file and in the stub.
634 */
635
636 static int
637 create_process (LPSTR exec_file, LPSTR args, DWORD flags, 
638                 PROCESS_INFORMATION * pi)
639 {
640   gdb_wince_len len;
641   LPWSTR buf;
642
643   buf = towide (exec_file, &len);
644   putmemory ("CreateProcess exec_file", GDB_CREATEPROCESS, buf, len);
645   buf = towide (args, &len);
646   putmemory ("CreateProcess args", GDB_CREATEPROCESS, buf, len);
647   putdword ("CreateProcess flags", GDB_CREATEPROCESS, flags);
648   return getresult ("CreateProcess result", GDB_CREATEPROCESS, pi, NULL);
649 }
650
651 /* Emulate TerminateProcess.  
652    Don't bother with the second argument since CE ignores it.
653  */
654 static int
655 terminate_process (HANDLE h)
656 {
657   gdb_wince_result res;
658   if (s < 0)
659     return 1;
660   puthandle ("TerminateProcess handle", GDB_TERMINATEPROCESS, h);
661
662   return getresult ("TerminateProcess result", 
663                     GDB_TERMINATEPROCESS, &res, NULL);
664 }
665
666 static int
667 wait_for_debug_event (DEBUG_EVENT * ev, DWORD ms)
668 {
669   if (s < 0)
670     return 1;
671   putdword ("WaitForDebugEvent ms", GDB_WAITFORDEBUGEVENT, ms);
672
673   return getresult ("WaitForDebugEvent event", 
674                     GDB_WAITFORDEBUGEVENT, ev, NULL);
675 }
676
677 static int
678 get_thread_context (HANDLE h, CONTEXT * c)
679 {
680   if (s < 0)
681     return 1;
682   puthandle ("GetThreadContext handle", GDB_GETTHREADCONTEXT, h);
683   putdword ("GetThreadContext flags", GDB_GETTHREADCONTEXT, 
684             c->ContextFlags);
685
686   return getresult ("GetThreadContext context", 
687                     GDB_GETTHREADCONTEXT, c, NULL);
688 }
689
690 static int
691 set_thread_context (HANDLE h, CONTEXT * c)
692 {
693   gdb_wince_result res;
694   if (s < 0)
695     return 1;
696   puthandle ("SetThreadContext handle", GDB_SETTHREADCONTEXT, h);
697   putmemory ("SetThreadContext context", GDB_SETTHREADCONTEXT, 
698              c, sizeof (*c));
699
700   return getresult ("SetThreadContext context", 
701                     GDB_SETTHREADCONTEXT, &res, NULL);
702 }
703
704 static int
705 read_process_memory (HANDLE h, LPCVOID where, 
706                      LPVOID buf, gdb_wince_len len, 
707                      gdb_wince_len * nbytes)
708 {
709   if (s < 0)
710     return 1;
711   puthandle ("ReadProcessMemory handle", GDB_READPROCESSMEMORY, h);
712   putpvoid ("ReadProcessMemory location", GDB_READPROCESSMEMORY, where);
713   putlen ("ReadProcessMemory size", GDB_READPROCESSMEMORY, len);
714
715   return getresult ("ReadProcessMemory buf", 
716                     GDB_READPROCESSMEMORY, buf, nbytes);
717 }
718
719 static int
720 write_process_memory (HANDLE h, LPCVOID where, 
721                       LPCVOID buf, gdb_wince_len len, 
722                       gdb_wince_len * nbytes)
723 {
724   if (s < 0)
725     return 1;
726   puthandle ("WriteProcessMemory handle", GDB_WRITEPROCESSMEMORY, h);
727   putpvoid ("WriteProcessMemory location", GDB_WRITEPROCESSMEMORY, where);
728   putmemory ("WriteProcProcessMemory buf", GDB_WRITEPROCESSMEMORY, buf, len);
729
730   return getresult ("WriteProcessMemory result", 
731                     GDB_WRITEPROCESSMEMORY, nbytes, NULL);
732 }
733
734 static int
735 remote_read_bytes (CORE_ADDR memaddr, char *myaddr, int len)
736 {
737   gdb_wince_len nbytes;
738   if (!read_process_memory (current_process_handle, 
739                             (LPCVOID) memaddr,
740                             (LPVOID) myaddr, 
741                             len, &nbytes))
742     return -1;
743   return nbytes;
744 }
745
746 static int
747 remote_write_bytes (CORE_ADDR memaddr, char *myaddr, int len)
748 {
749   gdb_wince_len nbytes;
750   if (!write_process_memory (current_process_handle, 
751                              (LPCVOID) memaddr, 
752                              (LPCVOID) myaddr, 
753                              len, &nbytes))
754     return -1;
755   return nbytes;
756 }
757
758 /* This is not a standard Win32 function.  It instructs the stub to
759    return TRUE if the thread referenced by HANDLE h is alive.
760  */
761 static int
762 thread_alive (HANDLE h)
763 {
764   gdb_wince_result res;
765   if (s < 0)
766     return 1;
767   puthandle ("ThreadAlive handle", GDB_THREADALIVE, h);
768   return getresult ("ThreadAlive result", GDB_THREADALIVE, &res, NULL);
769 }
770
771 static int
772 suspend_thread (HANDLE h)
773 {
774   if (s < 0)
775     return 1;
776   puthandle ("SuspendThread handle", GDB_SUSPENDTHREAD, h);
777   return (int) getdword ("SuspendThread result", GDB_SUSPENDTHREAD);
778 }
779
780 static int
781 resume_thread (HANDLE h)
782 {
783   if (s < 0)
784     return 1;
785   puthandle ("ResumeThread handle", GDB_RESUMETHREAD, h);
786   return (int) getdword ("SuspendThread result", GDB_RESUMETHREAD);
787 }
788
789 static int
790 continue_debug_event (DWORD pid, DWORD tid, DWORD status)
791 {
792   gdb_wince_result res;
793   if (s < 0)
794     return 0;
795   putdword ("ContinueDebugEvent pid", GDB_CONTINUEDEBUGEVENT, pid);
796   putdword ("ContinueDebugEvent tid", GDB_CONTINUEDEBUGEVENT, tid);
797   putdword ("ContinueDebugEvent status", GDB_CONTINUEDEBUGEVENT, status);
798   return getresult ("ContinueDebugEvent result", 
799                     GDB_CONTINUEDEBUGEVENT, &res, NULL);
800 }
801
802 static int
803 close_handle (HANDLE h)
804 {
805   gdb_wince_result res;
806   if (s < 0)
807     return 1;
808   puthandle ("CloseHandle handle", GDB_CLOSEHANDLE, h);
809   return (int) getresult ("CloseHandle result", 
810                           GDB_CLOSEHANDLE, &res, NULL);
811 }
812
813 /* This is not a standard Win32 interface.  This function tells the
814    stub to terminate.
815  */
816 static void
817 stop_stub (void)
818 {
819   if (s < 0)
820     return;
821   (void) putdword ("Stopping gdb stub", GDB_STOPSTUB, 0);
822   s = -1;
823 }
824
825 /******************** End of emulation routines. ********************/
826 /******************** End of stub interface ********************/
827
828 #define check_for_step(a, x) (x)
829
830 #ifdef MIPS
831 static void
832 undoSStep (thread_info * th)
833 {
834   if (th->stepped)
835     {
836       remove_single_step_breakpoints ();
837       th->stepped = 0;
838     }
839 }
840
841 void
842 wince_software_single_step (enum target_signal ignore,
843                             int insert_breakpoints_p)
844 {
845   unsigned long pc;
846   /* Info on currently selected thread.  */
847   thread_info *th = current_thread;
848   CORE_ADDR mips_next_pc (CORE_ADDR pc);
849
850   if (!insert_breakpoints_p)
851     {
852       undoSStep (th);
853       return;
854     }
855
856   th->stepped = 1;
857   pc = read_register (PC_REGNUM);
858   th->step_pc = mips_next_pc (pc);
859   insert_single_step_breakpoint (th->step_pc);
860   return;
861 }
862 #elif SHx
863 /* Renesas SH architecture instruction encoding masks */
864
865 #define COND_BR_MASK   0xff00
866 #define UCOND_DBR_MASK 0xe000
867 #define UCOND_RBR_MASK 0xf0df
868 #define TRAPA_MASK     0xff00
869
870 #define COND_DISP      0x00ff
871 #define UCOND_DISP     0x0fff
872 #define UCOND_REG      0x0f00
873
874 /* Renesas SH instruction opcodes */
875
876 #define BF_INSTR       0x8b00
877 #define BT_INSTR       0x8900
878 #define BRA_INSTR      0xa000
879 #define BSR_INSTR      0xb000
880 #define JMP_INSTR      0x402b
881 #define JSR_INSTR      0x400b
882 #define RTS_INSTR      0x000b
883 #define RTE_INSTR      0x002b
884 #define TRAPA_INSTR    0xc300
885 #define SSTEP_INSTR    0xc3ff
886
887
888 #define T_BIT_MASK     0x0001
889
890 static CORE_ADDR
891 sh_get_next_pc (CONTEXT *c)
892 {
893   short *instrMem;
894   int displacement;
895   int reg;
896   unsigned short opcode;
897
898   instrMem = (short *) c->Fir;
899
900   opcode = read_memory_integer ((CORE_ADDR) c->Fir, sizeof (opcode));
901
902   if ((opcode & COND_BR_MASK) == BT_INSTR)
903     {
904       if (c->Psr & T_BIT_MASK)
905         {
906           displacement = (opcode & COND_DISP) << 1;
907           if (displacement & 0x80)
908             displacement |= 0xffffff00;
909           /*
910              * Remember PC points to second instr.
911              * after PC of branch ... so add 4
912            */
913           instrMem = (short *) (c->Fir + displacement + 4);
914         }
915       else
916         instrMem += 1;
917     }
918   else if ((opcode & COND_BR_MASK) == BF_INSTR)
919     {
920       if (c->Psr & T_BIT_MASK)
921         instrMem += 1;
922       else
923         {
924           displacement = (opcode & COND_DISP) << 1;
925           if (displacement & 0x80)
926             displacement |= 0xffffff00;
927           /*
928              * Remember PC points to second instr.
929              * after PC of branch ... so add 4
930            */
931           instrMem = (short *) (c->Fir + displacement + 4);
932         }
933     }
934   else if ((opcode & UCOND_DBR_MASK) == BRA_INSTR)
935     {
936       displacement = (opcode & UCOND_DISP) << 1;
937       if (displacement & 0x0800)
938         displacement |= 0xfffff000;
939
940       /*
941          * Remember PC points to second instr.
942          * after PC of branch ... so add 4
943        */
944       instrMem = (short *) (c->Fir + displacement + 4);
945     }
946   else if ((opcode & UCOND_RBR_MASK) == JSR_INSTR)
947     {
948       reg = (char) ((opcode & UCOND_REG) >> 8);
949
950       instrMem = (short *) *regptr (c, reg);
951     }
952   else if (opcode == RTS_INSTR)
953     instrMem = (short *) c->PR;
954   else if (opcode == RTE_INSTR)
955     instrMem = (short *) *regptr (c, 15);
956   else if ((opcode & TRAPA_MASK) == TRAPA_INSTR)
957     instrMem = (short *) ((opcode & ~TRAPA_MASK) << 2);
958   else
959     instrMem += 1;
960
961   return (CORE_ADDR) instrMem;
962 }
963 /* Single step (in a painstaking fashion) by inspecting the current
964    instruction and setting a breakpoint on the "next" instruction
965    which would be executed.  This code hails from sh-stub.c.
966  */
967 static void
968 undoSStep (thread_info * th)
969 {
970   if (th->stepped)
971     {
972       remove_single_step_breakpoints ();
973       th->stepped = 0;
974     }
975   return;
976 }
977
978 /* Single step (in a painstaking fashion) by inspecting the current
979    instruction and setting a breakpoint on the "next" instruction
980    which would be executed.  This code hails from sh-stub.c.
981  */
982 void
983 wince_software_single_step (enum target_signal ignore,
984                             int insert_breakpoints_p)
985 {
986   /* Info on currently selected thread.  */
987   thread_info *th = current_thread;
988
989   if (!insert_breakpoints_p)
990     {
991       undoSStep (th);
992       return;
993     }
994
995   th->stepped = 1;
996   th->step_pc = sh_get_next_pc (&th->context);
997   insert_single_step_breakpoint (th->step_pc);
998   return;
999 }
1000 #elif defined (ARM)
1001 #undef check_for_step
1002
1003 static enum target_signal
1004 check_for_step (DEBUG_EVENT *ev, enum target_signal x)
1005 {
1006   thread_info *th = thread_rec (ev->dwThreadId, 1);
1007
1008   if (th->stepped &&
1009       th->step_pc == (CORE_ADDR) ev->u.Exception.ExceptionRecord.ExceptionAddress)
1010     return TARGET_SIGNAL_TRAP;
1011   else
1012     return x;
1013 }
1014
1015 /* Single step (in a painstaking fashion) by inspecting the current
1016    instruction and setting a breakpoint on the "next" instruction
1017    which would be executed.  This code hails from sh-stub.c.
1018  */
1019 static void
1020 undoSStep (thread_info * th)
1021 {
1022   if (th->stepped)
1023     {
1024       remove_single_step_breakpoints ();
1025       th->stepped = 0;
1026     }
1027 }
1028
1029 void
1030 wince_software_single_step (enum target_signal ignore,
1031                             int insert_breakpoints_p)
1032 {
1033   unsigned long pc;
1034   /* Info on currently selected thread.  */
1035   thread_info *th = current_thread;
1036   CORE_ADDR mips_next_pc (CORE_ADDR pc);
1037
1038   if (!insert_breakpoints_p)
1039     {
1040       undoSStep (th);
1041       return;
1042     }
1043
1044   th->stepped = 1;
1045   pc = read_register (PC_REGNUM);
1046   th->step_pc = arm_get_next_pc (pc);
1047   insert_single_step_breakpoint (th->step_pc);
1048   return;
1049 }
1050 #endif
1051
1052 /* Find a thread record given a thread id.
1053    If get_context then also retrieve the context for this thread.  */
1054
1055 static thread_info *
1056 thread_rec (DWORD id, int get_context)
1057 {
1058   thread_info *th;
1059
1060   for (th = &thread_head; (th = th->next) != NULL;)
1061     if (th->id == id)
1062       {
1063         if (!th->suspend_count && get_context)
1064           {
1065             if (get_context > 0 && th != this_thread)
1066               th->suspend_count = suspend_thread (th->h) + 1;
1067             else if (get_context < 0)
1068               th->suspend_count = -1;
1069
1070             th->context.ContextFlags = CONTEXT_DEBUGGER;
1071             get_thread_context (th->h, &th->context);
1072           }
1073         return th;
1074       }
1075   return NULL;
1076 }
1077
1078 /* Add a thread to the thread list.  */
1079 static thread_info *
1080 child_add_thread (DWORD id, HANDLE h)
1081 {
1082   thread_info *th;
1083
1084   if ((th = thread_rec (id, FALSE)))
1085     return th;
1086
1087   th = (thread_info *) xmalloc (sizeof (*th));
1088   memset (th, 0, sizeof (*th));
1089   th->id = id;
1090   th->h = h;
1091   th->next = thread_head.next;
1092   thread_head.next = th;
1093   add_thread (id);
1094   return th;
1095 }
1096
1097 /* Clear out any old thread list and reintialize it to a
1098    pristine state.  */
1099 static void
1100 child_init_thread_list (void)
1101 {
1102   thread_info *th = &thread_head;
1103
1104   DEBUG_EVENTS (("gdb: child_init_thread_list\n"));
1105   init_thread_list ();
1106   while (th->next != NULL)
1107     {
1108       thread_info *here = th->next;
1109       th->next = here->next;
1110       (void) close_handle (here->h);
1111       xfree (here);
1112     }
1113 }
1114
1115 /* Delete a thread from the list of threads.  */
1116 static void
1117 child_delete_thread (DWORD id)
1118 {
1119   thread_info *th;
1120
1121   if (info_verbose)
1122     printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (id));
1123   delete_thread (id);
1124
1125   for (th = &thread_head;
1126        th->next != NULL && th->next->id != id;
1127        th = th->next)
1128     continue;
1129
1130   if (th->next != NULL)
1131     {
1132       thread_info *here = th->next;
1133       th->next = here->next;
1134       close_handle (here->h);
1135       xfree (here);
1136     }
1137 }
1138
1139 static void
1140 check (BOOL ok, const char *file, int line)
1141 {
1142   if (!ok)
1143     printf_filtered ("error return %s:%d was %d\n", 
1144                      file, line, GetLastError ());
1145 }
1146
1147 static void
1148 do_child_fetch_inferior_registers (int r)
1149 {
1150   if (r >= 0)
1151     {
1152       regcache_raw_supply (current_regcache, r,
1153                            (char *) regptr (&current_thread->context, r));
1154     }
1155   else
1156     {
1157       for (r = 0; r < NUM_REGS; r++)
1158         do_child_fetch_inferior_registers (r);
1159     }
1160 }
1161
1162 static void
1163 child_fetch_inferior_registers (int r)
1164 {
1165   current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
1166   do_child_fetch_inferior_registers (r);
1167 }
1168
1169 static void
1170 do_child_store_inferior_registers (int r)
1171 {
1172   if (r >= 0)
1173     deprecated_read_register_gen (r, ((char *) &current_thread->context) + mappings[r]);
1174   else
1175     {
1176       for (r = 0; r < NUM_REGS; r++)
1177         do_child_store_inferior_registers (r);
1178     }
1179 }
1180
1181 /* Store a new register value into the current thread context.  */
1182 static void
1183 child_store_inferior_registers (int r)
1184 {
1185   current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
1186   do_child_store_inferior_registers (r);
1187 }
1188
1189 /* Wait for child to do something.  Return pid of child, or -1 in case
1190    of error; store status through argument pointer OURSTATUS.  */
1191
1192 static int
1193 handle_load_dll (void *dummy)
1194 {
1195   LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
1196   char dll_buf[MAX_PATH + 1];
1197   char *p, *bufp, *imgp, *dll_name, *dll_basename;
1198   int len;
1199
1200   dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
1201   if (!event->lpImageName)
1202     return 1;
1203
1204   len = 0;
1205   for (bufp = dll_buf, imgp = event->lpImageName;
1206        bufp < dll_buf + sizeof (dll_buf);
1207        bufp += 16, imgp += 16)
1208     {
1209       gdb_wince_len nbytes = 0;
1210       (void) read_process_memory (current_process_handle,
1211                                   imgp, bufp, 16, &nbytes);
1212
1213       if (!nbytes && bufp == dll_buf)
1214         return 1;               /* couldn't read it */
1215       for (p = bufp; p < bufp + nbytes; p++)
1216         {
1217           len++;
1218           if (*p == '\0')
1219             goto out;
1220           if (event->fUnicode)
1221             p++;
1222         }
1223       if (!nbytes)
1224         break;
1225     }
1226
1227 out:
1228   if (!len)
1229     return 1;
1230 #if 0
1231   dll_buf[len] = '\0';
1232 #endif
1233   dll_name = alloca (len);
1234
1235   if (!dll_name)
1236     return 1;
1237
1238   if (!event->fUnicode)
1239     memcpy (dll_name, dll_buf, len);
1240   else
1241     WideCharToMultiByte (CP_ACP, 0, (LPCWSTR) dll_buf,
1242                          len, dll_name, len, 0, 0);
1243
1244   while ((p = strchr (dll_name, '\\')))
1245     *p = '/';
1246
1247   /* FIXME!! It would be nice to define one symbol which pointed to
1248      the front of the dll if we can't find any symbols.  */
1249
1250   if (!(dll_basename = strrchr (dll_name, '/')))
1251     dll_basename = dll_name;
1252   else
1253     dll_basename++;
1254
1255   /* The symbols in a dll are offset by 0x1000, which is the
1256      the offset from 0 of the first byte in an image - because
1257      of the file header and the section alignment.
1258
1259      FIXME: Is this the real reason that we need the 0x1000 ? */
1260
1261   printf_unfiltered ("%x:%s", event->lpBaseOfDll, dll_name);
1262   printf_unfiltered ("\n");
1263
1264   return 1;
1265 }
1266
1267 /* Handle DEBUG_STRING output from child process.  */
1268 static void
1269 handle_output_debug_string (struct target_waitstatus *ourstatus)
1270 {
1271   char p[256];
1272   char s[255];
1273   char *q;
1274   gdb_wince_len nbytes_read;
1275   gdb_wince_len nbytes = current_event.u.DebugString.nDebugStringLength;
1276
1277   if (nbytes > 255)
1278     nbytes = 255;
1279
1280   memset (p, 0, sizeof (p));
1281   if (!read_process_memory (current_process_handle,
1282                             current_event.u.DebugString.lpDebugStringData,
1283                             &p, nbytes, &nbytes_read)
1284       || !*p)
1285     return;
1286
1287   memset (s, 0, sizeof (s));
1288   WideCharToMultiByte (CP_ACP, 0, (LPCWSTR) p, (int) nbytes_read,
1289                        s, sizeof (s) - 1, NULL, NULL);
1290   q = strchr (s, '\n');
1291   if (q != NULL)
1292     {
1293       *q = '\0';
1294       if (*--q = '\r')
1295         *q = '\0';
1296     }
1297
1298   warning (s);
1299
1300   return;
1301 }
1302
1303 /* Handle target exceptions.  */
1304 static int
1305 handle_exception (struct target_waitstatus *ourstatus)
1306 {
1307 #if 0
1308   if (current_event.u.Exception.dwFirstChance)
1309     return 0;
1310 #endif
1311
1312   ourstatus->kind = TARGET_WAITKIND_STOPPED;
1313
1314   switch (current_event.u.Exception.ExceptionRecord.ExceptionCode)
1315     {
1316     case EXCEPTION_ACCESS_VIOLATION:
1317       DEBUG_EXCEPT (("gdb: Target exception ACCESS_VIOLATION at 0x%08x\n",
1318                      (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1319       ourstatus->value.sig = TARGET_SIGNAL_SEGV;
1320       break;
1321     case STATUS_STACK_OVERFLOW:
1322       DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08x\n",
1323                      (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1324       ourstatus->value.sig = TARGET_SIGNAL_SEGV;
1325       break;
1326     case EXCEPTION_BREAKPOINT:
1327       DEBUG_EXCEPT (("gdb: Target exception BREAKPOINT at 0x%08x\n",
1328                      (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1329       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
1330       break;
1331     case DBG_CONTROL_C:
1332       DEBUG_EXCEPT (("gdb: Target exception CONTROL_C at 0x%08x\n",
1333                      (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1334       ourstatus->value.sig = TARGET_SIGNAL_INT;
1335       /* User typed CTRL-C.  Continue with this status.  */
1336       last_sig = SIGINT;        /* FIXME - should check pass state.  */
1337       break;
1338     case EXCEPTION_SINGLE_STEP:
1339       DEBUG_EXCEPT (("gdb: Target exception SINGLE_STEP at 0x%08x\n",
1340                      (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1341       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
1342       break;
1343     case EXCEPTION_ILLEGAL_INSTRUCTION:
1344       DEBUG_EXCEPT (("gdb: Target exception SINGLE_ILL at 0x%08x\n",
1345                      /* (unsigned)? */ current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1346       ourstatus->value.sig = check_for_step (&current_event, 
1347                                              TARGET_SIGNAL_ILL);
1348       break;
1349     default:
1350       /* This may be a structured exception handling exception.  In
1351          that case, we want to let the program try to handle it, and
1352          only break if we see the exception a second time.  */
1353
1354       printf_unfiltered 
1355         ("gdb: unknown target exception 0x%08x at 0x%08x\n",
1356          current_event.u.Exception.ExceptionRecord.ExceptionCode,
1357          current_event.u.Exception.ExceptionRecord.ExceptionAddress);
1358       ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
1359       break;
1360     }
1361   exception_count++;
1362   return 1;
1363 }
1364
1365 /* Resume all artificially suspended threads if we are continuing
1366    execution.  */
1367 static BOOL
1368 child_continue (DWORD continue_status, int id)
1369 {
1370   int i;
1371   thread_info *th;
1372   BOOL res;
1373
1374   DEBUG_EVENTS (("ContinueDebugEvent (cpid=%d, ctid=%d, DBG_CONTINUE);\n",
1375                  (unsigned) current_event.dwProcessId, 
1376                  (unsigned) current_event.dwThreadId));
1377   res = continue_debug_event (current_event.dwProcessId,
1378                               current_event.dwThreadId,
1379                               continue_status);
1380   if (res)
1381     for (th = &thread_head; (th = th->next) != NULL;)
1382       if (((id == -1) || (id == th->id)) && th->suspend_count)
1383         {
1384           for (i = 0; i < th->suspend_count; i++)
1385             (void) resume_thread (th->h);
1386           th->suspend_count = 0;
1387         }
1388
1389   return res;
1390 }
1391
1392 /* Get the next event from the child.  Return 1 if the event requires
1393    handling by WFI (or whatever).
1394  */
1395 static int
1396 get_child_debug_event (int pid, struct target_waitstatus *ourstatus,
1397                        DWORD target_event_code, int *retval)
1398 {
1399   int breakout = 0;
1400   BOOL debug_event;
1401   DWORD continue_status, event_code;
1402   thread_info *th = NULL;
1403   static thread_info dummy_thread_info;
1404
1405   if (!(debug_event = wait_for_debug_event (&current_event, 1000)))
1406     {
1407       *retval = 0;
1408       goto out;
1409     }
1410
1411   event_count++;
1412   continue_status = DBG_CONTINUE;
1413   *retval = 0;
1414
1415   event_code = current_event.dwDebugEventCode;
1416   breakout = event_code == target_event_code;
1417
1418   switch (event_code)
1419     {
1420     case CREATE_THREAD_DEBUG_EVENT:
1421       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
1422                      (unsigned) current_event.dwProcessId,
1423                      (unsigned) current_event.dwThreadId,
1424                      "CREATE_THREAD_DEBUG_EVENT"));
1425       /* Record the existence of this thread */
1426       th = child_add_thread (current_event.dwThreadId,
1427                              current_event.u.CreateThread.hThread);
1428       if (info_verbose)
1429         printf_unfiltered ("[New %s]\n",
1430                            target_pid_to_str (current_event.dwThreadId));
1431       break;
1432
1433     case EXIT_THREAD_DEBUG_EVENT:
1434       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1435                      (unsigned) current_event.dwProcessId,
1436                      (unsigned) current_event.dwThreadId,
1437                      "EXIT_THREAD_DEBUG_EVENT"));
1438       child_delete_thread (current_event.dwThreadId);
1439       th = &dummy_thread_info;
1440       break;
1441
1442     case CREATE_PROCESS_DEBUG_EVENT:
1443       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1444                      (unsigned) current_event.dwProcessId,
1445                      (unsigned) current_event.dwThreadId,
1446                      "CREATE_PROCESS_DEBUG_EVENT"));
1447       current_process_handle = current_event.u.CreateProcessInfo.hProcess;
1448
1449       main_thread_id = current_event.dwThreadId;
1450       inferior_ptid = pid_to_ptid (main_thread_id);
1451       /* Add the main thread */
1452       th = child_add_thread (PIDGET (inferior_ptid),
1453                              current_event.u.CreateProcessInfo.hThread);
1454       break;
1455
1456     case EXIT_PROCESS_DEBUG_EVENT:
1457       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1458                      (unsigned) current_event.dwProcessId,
1459                      (unsigned) current_event.dwThreadId,
1460                      "EXIT_PROCESS_DEBUG_EVENT"));
1461       ourstatus->kind = TARGET_WAITKIND_EXITED;
1462       ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
1463       close_handle (current_process_handle);
1464       *retval = current_event.dwProcessId;
1465       breakout = 1;
1466       break;
1467
1468     case LOAD_DLL_DEBUG_EVENT:
1469       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1470                      (unsigned) current_event.dwProcessId,
1471                      (unsigned) current_event.dwThreadId,
1472                      "LOAD_DLL_DEBUG_EVENT"));
1473       catch_errors (handle_load_dll, NULL, 
1474                     (char *) "", RETURN_MASK_ALL);
1475       registers_changed ();     /* mark all regs invalid */
1476       break;
1477
1478     case UNLOAD_DLL_DEBUG_EVENT:
1479       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1480                      (unsigned) current_event.dwProcessId,
1481                      (unsigned) current_event.dwThreadId,
1482                      "UNLOAD_DLL_DEBUG_EVENT"));
1483       break;                    /* FIXME: don't know what to do here */
1484
1485     case EXCEPTION_DEBUG_EVENT:
1486       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1487                      (unsigned) current_event.dwProcessId,
1488                      (unsigned) current_event.dwThreadId,
1489                      "EXCEPTION_DEBUG_EVENT"));
1490       if (handle_exception (ourstatus))
1491         *retval = current_event.dwThreadId;
1492       else
1493         {
1494           continue_status = DBG_EXCEPTION_NOT_HANDLED;
1495           breakout = 0;
1496         }
1497       break;
1498
1499     case OUTPUT_DEBUG_STRING_EVENT:     /* message from the kernel */
1500       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1501                      (unsigned) current_event.dwProcessId,
1502                      (unsigned) current_event.dwThreadId,
1503                      "OUTPUT_DEBUG_STRING_EVENT"));
1504       handle_output_debug_string ( ourstatus);
1505       break;
1506     default:
1507       printf_unfiltered ("gdb: kernel event for pid=%d tid=%d\n",
1508                          current_event.dwProcessId,
1509                          current_event.dwThreadId);
1510       printf_unfiltered ("                 unknown event code %d\n",
1511                          current_event.dwDebugEventCode);
1512       break;
1513     }
1514
1515   if (breakout)
1516     this_thread = current_thread = th ?: thread_rec (current_event.dwThreadId,
1517                                                      TRUE);
1518   else
1519     CHECK (child_continue (continue_status, -1));
1520
1521 out:
1522   return breakout;
1523 }
1524
1525 /* Wait for interesting events to occur in the target process.  */
1526 static ptid_t
1527 child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
1528 {
1529   DWORD event_code;
1530   int retval;
1531   int pid = PIDGET (ptid);
1532
1533   /* We loop when we get a non-standard exception rather than return
1534      with a SPURIOUS because resume can try and step or modify things,
1535      which needs a current_thread->h.  But some of these exceptions mark
1536      the birth or death of threads, which mean that the current thread
1537      isn't necessarily what you think it is.  */
1538
1539   while (1)
1540     if (get_child_debug_event (pid, ourstatus, 
1541                                EXCEPTION_DEBUG_EVENT, &retval))
1542       return pid_to_ptid (retval);
1543     else
1544       {
1545         int detach = 0;
1546
1547         if (deprecated_ui_loop_hook != NULL)
1548           detach = deprecated_ui_loop_hook (0);
1549
1550         if (detach)
1551           child_kill_inferior ();
1552       }
1553 }
1554
1555 /* Print status information about what we're accessing.  */
1556
1557 static void
1558 child_files_info (struct target_ops *ignore)
1559 {
1560   printf_unfiltered ("\tUsing the running image of child %s.\n",
1561                      target_pid_to_str (inferior_ptid));
1562 }
1563
1564 static void
1565 child_open (char *arg, int from_tty)
1566 {
1567   error (_("Use the \"run\" command to start a child process."));
1568 }
1569
1570 #define FACTOR (0x19db1ded53ea710LL)
1571 #define NSPERSEC 10000000
1572
1573 /* Convert a Win32 time to "UNIX" format.  */
1574 long
1575 to_time_t (FILETIME * ptr)
1576 {
1577   /* A file time is the number of 100ns since jan 1 1601
1578      stuffed into two long words.
1579      A time_t is the number of seconds since jan 1 1970.  */
1580
1581   long rem;
1582   long long x = ((long long) ptr->dwHighDateTime << 32) + ((unsigned) ptr->dwLowDateTime);
1583   x -= FACTOR;                  /* Number of 100ns between 1601 and 1970.  */
1584   rem = x % ((long long) NSPERSEC);
1585   rem += (NSPERSEC / 2);
1586   x /= (long long) NSPERSEC;    /* Number of 100ns in a second.  */
1587   x += (long long) (rem / NSPERSEC);
1588   return x;
1589 }
1590
1591 /* Upload a file to the remote device depending on the user's
1592    'set remoteupload' specification.  */
1593 char *
1594 upload_to_device (const char *to, const char *from)
1595 {
1596   HANDLE h;
1597   const char *dir = remote_directory ?: "\\gdb";
1598   int len;
1599   static char *remotefile = NULL;
1600   LPWSTR wstr;
1601   char *p;
1602   DWORD err;
1603   const char *in_to = to;
1604   FILETIME crtime, actime, wrtime;
1605   time_t utime;
1606   struct stat st;
1607   int fd;
1608
1609   /* Look for a path separator and only use trailing part.  */
1610   while ((p = strpbrk (to, "/\\")) != NULL)
1611     to = p + 1;
1612
1613   if (!*to)
1614     error (_("no filename found to upload - %s."), in_to);
1615
1616   len = strlen (dir) + strlen (to) + 2;
1617   remotefile = (char *) xrealloc (remotefile, len);
1618   strcpy (remotefile, dir);
1619   strcat (remotefile, "\\");
1620   strcat (remotefile, to);
1621
1622   if (upload_when == UPLOAD_NEVER)
1623     return remotefile;          /* Don't bother uploading.  */
1624
1625   /* Open the source.  */
1626   if ((fd = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, (char *) from,
1627                    O_RDONLY, 0, NULL)) < 0)
1628     error (_("couldn't open %s"), from);
1629
1630   /* Get the time for later comparison.  */
1631   if (fstat (fd, &st))
1632     st.st_mtime = (time_t) - 1;
1633
1634   /* Always attempt to create the directory on the remote system.  */
1635   wstr = towide (dir, NULL);
1636   (void) CeCreateDirectory (wstr, NULL);
1637
1638   /* Attempt to open the remote file, creating it if it doesn't exist.  */
1639   wstr = towide (remotefile, NULL);
1640   h = CeCreateFile (wstr, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1641                     OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1642
1643   /* Some kind of problem?  */
1644   err = CeGetLastError ();
1645   if (h == NULL || h == INVALID_HANDLE_VALUE)
1646     error (_("error opening file \"%s\".  Windows error %d."),
1647            remotefile, err);
1648
1649   CeGetFileTime (h, &crtime, &actime, &wrtime);
1650   utime = to_time_t (&wrtime);
1651 #if 0
1652   if (utime < st.st_mtime)
1653     {
1654       char buf[80];
1655       strcpy (buf, ctime(&utime));
1656       printf ("%s < %s\n", buf, ctime(&st.st_mtime));
1657     }
1658 #endif
1659   /* See if we need to upload the file.  */
1660   if (upload_when == UPLOAD_ALWAYS ||
1661       err != ERROR_ALREADY_EXISTS ||
1662       !CeGetFileTime (h, &crtime, &actime, &wrtime) ||
1663       to_time_t (&wrtime) < st.st_mtime)
1664     {
1665       DWORD nbytes;
1666       char buf[4096];
1667       int n;
1668
1669       /* Upload the file.  */
1670       while ((n = read (fd, buf, sizeof (buf))) > 0)
1671         if (!CeWriteFile (h, buf, (DWORD) n, &nbytes, NULL))
1672           error (_("error writing to remote device - %d."),
1673                  CeGetLastError ());
1674     }
1675
1676   close (fd);
1677   if (!CeCloseHandle (h))
1678     error (_("error closing remote file - %d."), CeGetLastError ());
1679
1680   return remotefile;
1681 }
1682
1683 /* Initialize the connection to the remote device.  */
1684 static void
1685 wince_initialize (void)
1686 {
1687   int tmp;
1688   char args[256];
1689   char *hostname;
1690   struct sockaddr_in sin;
1691   char *stub_file_name;
1692   int s0;
1693   PROCESS_INFORMATION pi;
1694
1695   if (!connection_initialized)
1696     switch (CeRapiInit ())
1697       {
1698       case 0:
1699         connection_initialized = 1;
1700         break;
1701       default:
1702         CeRapiUninit ();
1703         error (_("Can't initialize connection to remote device."));
1704       }
1705
1706   /* Upload the stub to the handheld device.  */
1707   stub_file_name = upload_to_device ("wince-stub.exe", WINCE_STUB);
1708   strcpy (args, stub_file_name);
1709
1710   if (remote_add_host)
1711     {
1712       strcat (args, " ");
1713       hostname = strchr (args, '\0');
1714       if (gethostname (hostname, sizeof (args) - strlen (args)))
1715         error (_("couldn't get hostname of this system."));
1716     }
1717
1718   /* Get a socket.  */
1719   if ((s0 = socket (AF_INET, SOCK_STREAM, 0)) < 0)
1720     stub_error ("Couldn't connect to host system.");
1721
1722   /* Allow rapid reuse of the port.  */
1723   tmp = 1;
1724   (void) setsockopt (s0, SOL_SOCKET, SO_REUSEADDR, 
1725                      (char *) &tmp, sizeof (tmp));
1726
1727
1728   /* Set up the information for connecting to the host gdb process.  */
1729   memset (&sin, 0, sizeof (sin));
1730   sin.sin_family = AF_INET;
1731   sin.sin_port = htons (7000);  /* FIXME: This should be configurable.  */
1732
1733   if (bind (s0, (struct sockaddr *) &sin, sizeof (sin)))
1734     error (_("couldn't bind socket"));
1735
1736   if (listen (s0, 1))
1737     error (_("Couldn't open socket for listening."));
1738
1739   /* Start up the stub on the remote device.  */
1740   if (!CeCreateProcess (towide (stub_file_name, NULL), 
1741                         towide (args, NULL),
1742                         NULL, NULL, 0, 0, 
1743                         NULL, NULL, NULL, &pi))
1744     error (_("Unable to start remote stub '%s'.  Windows CE error %d."),
1745            stub_file_name, CeGetLastError ());
1746
1747   /* Wait for a connection */
1748
1749   if ((s = accept (s0, NULL, NULL)) < 0)
1750     error (_("couldn't set up server for connection."));
1751
1752   close (s0);
1753 }
1754
1755 /* Start an inferior win32 child process and sets inferior_ptid to its pid.
1756    EXEC_FILE is the file to run.
1757    ALLARGS is a string containing the arguments to the program.
1758    ENV is the environment vector to pass.  
1759    Errors reported with error().  */
1760 static void
1761 child_create_inferior (char *exec_file, char *args, char **env,
1762                        int from_tty)
1763 {
1764   PROCESS_INFORMATION pi;
1765   struct target_waitstatus dummy;
1766   int ret;
1767   DWORD flags, event_code;
1768   char *exec_and_args;
1769
1770   if (!exec_file)
1771     error (_("No executable specified, use `target exec'."));
1772
1773   flags = DEBUG_PROCESS;
1774
1775   wince_initialize ();          /* Make sure we've got a connection.  */
1776
1777   exec_file = upload_to_device (exec_file, exec_file);
1778
1779   while (*args == ' ')
1780     args++;
1781
1782   /* Allocate space for "command<sp>args" */
1783   if (*args == '\0')
1784     {
1785       exec_and_args = alloca (strlen (exec_file) + 1);
1786       strcpy (exec_and_args, exec_file);
1787     }
1788   else
1789     {
1790       exec_and_args = alloca (strlen (exec_file + strlen (args) + 2));
1791       sprintf (exec_and_args, "%s %s", exec_file, args);
1792     }
1793
1794   memset (&pi, 0, sizeof (pi));
1795   /* Execute the process.  */
1796   if (!create_process (exec_file, exec_and_args, flags, &pi))
1797     error (_("Error creating process %s, (error %d)."), 
1798            exec_file, GetLastError ());
1799
1800   exception_count = 0;
1801   event_count = 0;
1802
1803   current_process_handle = pi.hProcess;
1804   current_event.dwProcessId = pi.dwProcessId;
1805   memset (&current_event, 0, sizeof (current_event));
1806   current_event.dwThreadId = pi.dwThreadId;
1807   inferior_ptid = pid_to_ptid (current_event.dwThreadId);
1808   push_target (&deprecated_child_ops);
1809   child_init_thread_list ();
1810   child_add_thread (pi.dwThreadId, pi.hThread);
1811   init_wait_for_inferior ();
1812   clear_proceed_status ();
1813   target_terminal_init ();
1814   target_terminal_inferior ();
1815
1816   /* Run until process and threads are loaded */
1817   while (!get_child_debug_event (PIDGET (inferior_ptid), &dummy,
1818                                  CREATE_PROCESS_DEBUG_EVENT, &ret))
1819     continue;
1820 }
1821
1822 /* Chile has gone bye-bye.  */
1823 static void
1824 child_mourn_inferior (void)
1825 {
1826   (void) child_continue (DBG_CONTINUE, -1);
1827   unpush_target (&deprecated_child_ops);
1828   stop_stub ();
1829   CeRapiUninit ();
1830   connection_initialized = 0;
1831   generic_mourn_inferior ();
1832 }
1833
1834 /* Move memory from child to/from gdb.  */
1835 int
1836 child_xfer_memory (CORE_ADDR memaddr, gdb_byte *our, 
1837                    int len, int write,
1838                    struct mem_attrib *attrib,
1839                    struct target_ops *target)
1840 {
1841   if (len <= 0)
1842     return 0;
1843
1844   if (write)
1845     res = remote_write_bytes (memaddr, our, len);
1846   else
1847     res = remote_read_bytes (memaddr, our, len);
1848
1849   return res;
1850 }
1851
1852 /* Terminate the process and wait for child to tell us it has
1853    completed.  */
1854 void
1855 child_kill_inferior (void)
1856 {
1857   CHECK (terminate_process (current_process_handle));
1858
1859   for (;;)
1860     {
1861       if (!child_continue (DBG_CONTINUE, -1))
1862         break;
1863       if (!wait_for_debug_event (&current_event, INFINITE))
1864         break;
1865       if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
1866         break;
1867     }
1868
1869   CHECK (close_handle (current_process_handle));
1870   close_handle (current_thread->h);
1871   target_mourn_inferior ();     /* or just child_mourn_inferior?  */
1872 }
1873
1874 /* Resume the child after an exception.  */
1875 void
1876 child_resume (ptid_t ptid, int step, enum target_signal sig)
1877 {
1878   thread_info *th;
1879   DWORD continue_status = last_sig > 0 && last_sig < NSIG ?
1880     DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE;
1881   int pid = PIDGET (ptid);
1882
1883   DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, sig=%d);\n",
1884                pid, step, sig));
1885
1886   /* Get context for currently selected thread */
1887   th = thread_rec (current_event.dwThreadId, FALSE);
1888
1889   if (th->context.ContextFlags)
1890     {
1891       CHECK (set_thread_context (th->h, &th->context));
1892       th->context.ContextFlags = 0;
1893     }
1894
1895   /* Allow continuing with the same signal that interrupted us.
1896      Otherwise complain.  */
1897   if (sig && sig != last_sig)
1898     fprintf_unfiltered (gdb_stderr, 
1899                         "Can't send signals to the child.  signal %d\n", 
1900                         sig);
1901
1902   last_sig = 0;
1903   child_continue (continue_status, pid);
1904 }
1905
1906 static void
1907 child_prepare_to_store (void)
1908 {
1909   /* Do nothing, since we can store individual regs */
1910 }
1911
1912 static int
1913 child_can_run (void)
1914 {
1915   return 1;
1916 }
1917
1918 static void
1919 child_close (void)
1920 {
1921   DEBUG_EVENTS (("gdb: child_close, inferior_ptid=%d\n",
1922                  PIDGET (inferior_ptid)));
1923 }
1924
1925 /* Explicitly upload file to remotedir */
1926
1927 static void
1928 child_load (char *file, int from_tty)
1929 {
1930   upload_to_device (file, file);
1931 }
1932
1933 static void
1934 init_child_ops (void)
1935 {
1936   memset (&deprecated_child_ops, 0, sizeof (deprecated_child_ops));
1937   deprecated_child_ops.to_shortname = (char *) "child";
1938   deprecated_child_ops.to_longname = (char *) "Windows CE process";
1939   deprecated_child_ops.to_doc = (char *) "Windows CE process (started by the \"run\" command).";
1940   deprecated_child_ops.to_open = child_open;
1941   deprecated_child_ops.to_close = child_close;
1942   deprecated_child_ops.to_resume = child_resume;
1943   deprecated_child_ops.to_wait = child_wait;
1944   deprecated_child_ops.to_fetch_registers = child_fetch_inferior_registers;
1945   deprecated_child_ops.to_store_registers = child_store_inferior_registers;
1946   deprecated_child_ops.to_prepare_to_store = child_prepare_to_store;
1947   deprecated_child_ops.deprecated_xfer_memory = child_xfer_memory;
1948   deprecated_child_ops.to_files_info = child_files_info;
1949   deprecated_child_ops.to_insert_breakpoint = memory_insert_breakpoint;
1950   deprecated_child_ops.to_remove_breakpoint = memory_remove_breakpoint;
1951   deprecated_child_ops.to_terminal_init = terminal_init_inferior;
1952   deprecated_child_ops.to_terminal_inferior = terminal_inferior;
1953   deprecated_child_ops.to_terminal_ours_for_output = terminal_ours_for_output;
1954   deprecated_child_ops.to_terminal_ours = terminal_ours;
1955   deprecated_child_ops.to_terminal_save_ours = terminal_save_ours;
1956   deprecated_child_ops.to_terminal_info = child_terminal_info;
1957   deprecated_child_ops.to_kill = child_kill_inferior;
1958   deprecated_child_ops.to_load = child_load;
1959   deprecated_child_ops.to_create_inferior = child_create_inferior;
1960   deprecated_child_ops.to_mourn_inferior = child_mourn_inferior;
1961   deprecated_child_ops.to_can_run = child_can_run;
1962   deprecated_child_ops.to_thread_alive = win32_child_thread_alive;
1963   deprecated_child_ops.to_stratum = process_stratum;
1964   deprecated_child_ops.to_has_all_memory = 1;
1965   deprecated_child_ops.to_has_memory = 1;
1966   deprecated_child_ops.to_has_stack = 1;
1967   deprecated_child_ops.to_has_registers = 1;
1968   deprecated_child_ops.to_has_execution = 1;
1969   deprecated_child_ops.to_magic = OPS_MAGIC;
1970 }
1971
1972
1973 /* Handle 'set remoteupload' parameter.  */
1974
1975 #define replace_upload(what) \
1976     upload_when = what; \
1977     remote_upload = xrealloc (remote_upload, \
1978                               strlen (upload_options[upload_when].name) + 1); \
1979     strcpy (remote_upload, upload_options[upload_when].name);
1980
1981 static void
1982 set_upload_type (char *ignore, int from_tty)
1983 {
1984   int i, len;
1985   char *bad_option;
1986
1987   if (!remote_upload || !remote_upload[0])
1988     {
1989       replace_upload (UPLOAD_NEWER);
1990       if (from_tty)
1991         printf_unfiltered ("Upload upload_options are: always, newer, never.\n");
1992       return;
1993     }
1994
1995   len = strlen (remote_upload);
1996   for (i = 0; 
1997        i < (sizeof (upload_options) / sizeof (upload_options[0])); 
1998        i++)
1999     if (len >= upload_options[i].abbrev &&
2000         strncasecmp (remote_upload, upload_options[i].name, len) == 0)
2001       {
2002         replace_upload (i);
2003         return;
2004       }
2005
2006   bad_option = remote_upload;
2007   replace_upload (UPLOAD_NEWER);
2008   error (_("Unknown upload type: %s."), bad_option);
2009 }
2010
2011 void
2012 _initialize_wince (void)
2013 {
2014   struct cmd_list_element *set;
2015   init_child_ops ();
2016
2017   add_setshow_string_noescape_cmd ("remotedirectory", no_class,
2018                                    &remote_directory, _("\
2019 Set directory for remote upload."), _("\
2020 Show directory for remote upload."), NULL,
2021                                    NULL, /* FIXME: i18n: */
2022                                    NULL, NULL,
2023                                    &setlist, &showlist);
2024   remote_directory = xstrdup (remote_directory);
2025
2026   add_setshow_string_noescape_cmd ("remoteupload", no_class,
2027                                    &remote_upload, _("\
2028 Set how to upload executables to remote device."), _("\
2029 Show how to upload executables to remote device."), NULL,
2030                                    NULL, /* FIXME: i18n: */
2031                                    set_upload_type, NULL,
2032                                    &setlist, &showlist);
2033   set_upload_type (NULL, 0);
2034
2035   add_setshow_boolean_cmd ("debugexec", class_support, &debug_exec, _("\
2036 Set whether to display execution in child process."), _("\
2037 Show whether to display execution in child process."), NULL,
2038                            NULL,
2039                            NULL, /* FIXME: i18n: */
2040                            &setlist, &showlist);
2041
2042   add_setshow_boolean_cmd ("remoteaddhost", class_support,
2043                            &remote_add_host, _("\
2044 Set whether to add this host to remote stub arguments for\n\
2045 debugging over a network."), _("\
2046 Show whether to add this host to remote stub arguments for\n\
2047 debugging over a network."), NULL,
2048                            NULL,
2049                            NULL, /* FIXME: i18n: */
2050                            &setlist, &showlist);
2051
2052   add_setshow_boolean_cmd ("debugevents", class_support, &debug_events, _("\
2053 Set whether to display kernel events in child process."), _("\
2054 Show whether to display kernel events in child process."), NULL,
2055                            NULL,
2056                            NULL, /* FIXME: i18n: */
2057                            &setlist, &showlist);
2058
2059   add_setshow_boolean_cmd ("debugmemory", class_support, &debug_memory, _("\
2060 Set whether to display memory accesses in child process."), _("\
2061 Show whether to display memory accesses in child process."), NULL,
2062                            NULL,
2063                            NULL, /* FIXME: i18n: */
2064                            &setlist, &showlist);
2065
2066   add_setshow_boolean_cmd ("debugexceptions", class_support,
2067                            &debug_exceptions, _("\
2068 Set whether to display kernel exceptions in child process."), _("\
2069 Show whether to display kernel exceptions in child process."), NULL,
2070                            NULL,
2071                            NULL, /* FIXME: i18n: */
2072                            &setlist, &showlist);
2073
2074   add_target (&deprecated_child_ops);
2075 }
2076
2077 /* Determine if the thread referenced by "pid" is alive by "polling"
2078    it.  If WaitForSingleObject returns WAIT_OBJECT_0 it means that the
2079    pid has died.  Otherwise it is assumed to be alive.  */
2080 static int
2081 win32_child_thread_alive (ptid_t ptid)
2082 {
2083   int pid = PIDGET (ptid);
2084   return thread_alive (thread_rec (pid, FALSE)->h);
2085 }
2086
2087 /* Convert pid to printable format.  */
2088 char *
2089 cygwin_pid_to_str (int pid)
2090 {
2091   static char buf[80];
2092   if (pid == current_event.dwProcessId)
2093     sprintf (buf, "process %d", pid);
2094   else
2095     sprintf (buf, "thread %d.0x%x", 
2096              (unsigned) current_event.dwProcessId, pid);
2097   return buf;
2098 }