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