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