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