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