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