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