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