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