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