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