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 (¤t_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 *) ¤t_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 = ¤t_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 (¤t_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 (¤t_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 (¤t_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 (¤t_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