Typo fix.
[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
ca0b4d12 30#define SH4 /* Just to get all of the CONTEXT defines. */
0f07afe1
CF
31#endif
32
33#include "defs.h"
ca0b4d12 34#include "frame.h" /* required by inferior.h */
0f07afe1
CF
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
ca0b4d12 67 headers in the first place since they were our own invention... */
0f07afe1
CF
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.
ca0b4d12 83 FIXME: This should be in a cygwin include file. */
0f07afe1
CF
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
ca0b4d12
MS
92static int connection_initialized = 0; /* True if we've initialized a
93 RAPI session. */
0f07afe1 94
ca0b4d12 95/* The directory where the stub and executable files are uploaded. */
0f07afe1
CF
96static const char *remote_directory = "\\gdb";
97
ca0b4d12 98/* The types automatic upload available. */
0f07afe1
CF
99static enum
100 {
101 UPLOAD_ALWAYS = 0,
102 UPLOAD_NEWER = 1,
103 UPLOAD_NEVER = 2
104 }
105upload_when = UPLOAD_NEWER;
106
107/* Valid options for 'set remoteupload'. Note that options
ca0b4d12 108 must track upload_when enum. */
0f07afe1
CF
109static struct opts
110 {
111 const char *name;
112 int abbrev;
113 }
114upload_options[3] =
115{
116 {
117 "always", 1
118 }
119 ,
120 {
121 "newer", 3
122 }
123 ,
124 {
125 "never", 3
126 }
127};
128
ca0b4d12 129static char *remote_upload = NULL; /* Set by set remoteupload. */
0f07afe1
CF
130static int remote_add_host = 0;
131
39f77062 132static int win32_child_thread_alive (ptid_t);
a14ed312 133void child_kill_inferior (void);
0f07afe1 134
ca0b4d12
MS
135static int last_sig = 0; /* Set if a signal was received from
136 the debugged process. */
0f07afe1
CF
137
138/* Thread information structure used to track information that is
ca0b4d12 139 not available in gdb's thread structure. */
0f07afe1
CF
140typedef struct thread_info_struct
141 {
142 struct thread_info_struct *next;
143 DWORD id;
144 HANDLE h;
145 char *name;
146 int suspend_count;
ca0b4d12 147 int stepped; /* True if stepped. */
0f07afe1 148 CORE_ADDR step_pc;
0f07afe1
CF
149 unsigned long step_prev;
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 {
837 memory_remove_breakpoint (th->step_pc, (void *) &th->step_prev);
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);
860 th->step_prev = 0;
861 memory_insert_breakpoint (th->step_pc, (void *) &th->step_prev);
862 return;
863}
864#elif SHx
85a453d5 865/* Renesas SH architecture instruction encoding masks */
61c37cee
CF
866
867#define COND_BR_MASK 0xff00
868#define UCOND_DBR_MASK 0xe000
869#define UCOND_RBR_MASK 0xf0df
870#define TRAPA_MASK 0xff00
871
872#define COND_DISP 0x00ff
873#define UCOND_DISP 0x0fff
874#define UCOND_REG 0x0f00
875
85a453d5 876/* Renesas SH instruction opcodes */
61c37cee
CF
877
878#define BF_INSTR 0x8b00
879#define BT_INSTR 0x8900
880#define BRA_INSTR 0xa000
881#define BSR_INSTR 0xb000
882#define JMP_INSTR 0x402b
883#define JSR_INSTR 0x400b
884#define RTS_INSTR 0x000b
885#define RTE_INSTR 0x002b
886#define TRAPA_INSTR 0xc300
887#define SSTEP_INSTR 0xc3ff
888
889
890#define T_BIT_MASK 0x0001
891
892static CORE_ADDR
893sh_get_next_pc (CONTEXT *c)
894{
895 short *instrMem;
896 int displacement;
897 int reg;
898 unsigned short opcode;
899
900 instrMem = (short *) c->Fir;
901
902 opcode = read_memory_integer ((CORE_ADDR) c->Fir, sizeof (opcode));
903
904 if ((opcode & COND_BR_MASK) == BT_INSTR)
905 {
906 if (c->Psr & T_BIT_MASK)
907 {
908 displacement = (opcode & COND_DISP) << 1;
909 if (displacement & 0x80)
910 displacement |= 0xffffff00;
911 /*
912 * Remember PC points to second instr.
913 * after PC of branch ... so add 4
914 */
915 instrMem = (short *) (c->Fir + displacement + 4);
916 }
917 else
918 instrMem += 1;
919 }
920 else if ((opcode & COND_BR_MASK) == BF_INSTR)
921 {
922 if (c->Psr & T_BIT_MASK)
923 instrMem += 1;
924 else
925 {
926 displacement = (opcode & COND_DISP) << 1;
927 if (displacement & 0x80)
928 displacement |= 0xffffff00;
929 /*
930 * Remember PC points to second instr.
931 * after PC of branch ... so add 4
932 */
933 instrMem = (short *) (c->Fir + displacement + 4);
934 }
935 }
936 else if ((opcode & UCOND_DBR_MASK) == BRA_INSTR)
937 {
938 displacement = (opcode & UCOND_DISP) << 1;
939 if (displacement & 0x0800)
940 displacement |= 0xfffff000;
941
942 /*
943 * Remember PC points to second instr.
944 * after PC of branch ... so add 4
945 */
946 instrMem = (short *) (c->Fir + displacement + 4);
947 }
948 else if ((opcode & UCOND_RBR_MASK) == JSR_INSTR)
949 {
950 reg = (char) ((opcode & UCOND_REG) >> 8);
951
952 instrMem = (short *) *regptr (c, reg);
953 }
954 else if (opcode == RTS_INSTR)
955 instrMem = (short *) c->PR;
956 else if (opcode == RTE_INSTR)
957 instrMem = (short *) *regptr (c, 15);
958 else if ((opcode & TRAPA_MASK) == TRAPA_INSTR)
959 instrMem = (short *) ((opcode & ~TRAPA_MASK) << 2);
960 else
961 instrMem += 1;
962
963 return (CORE_ADDR) instrMem;
964}
965/* Single step (in a painstaking fashion) by inspecting the current
966 instruction and setting a breakpoint on the "next" instruction
967 which would be executed. This code hails from sh-stub.c.
968 */
969static void
970undoSStep (thread_info * th)
971{
972 if (th->stepped)
973 {
974 memory_remove_breakpoint (th->step_pc, (void *) &th->step_prev);
975 th->stepped = 0;
976 }
977 return;
978}
979
980/* Single step (in a painstaking fashion) by inspecting the current
981 instruction and setting a breakpoint on the "next" instruction
982 which would be executed. This code hails from sh-stub.c.
983 */
984void
379d08a1
AC
985wince_software_single_step (enum target_signal ignore,
986 int insert_breakpoints_p)
61c37cee 987{
ca0b4d12
MS
988 /* Info on currently selected thread. */
989 thread_info *th = current_thread;
61c37cee
CF
990
991 if (!insert_breakpoints_p)
992 {
993 undoSStep (th);
994 return;
995 }
996
997 th->stepped = 1;
998 th->step_pc = sh_get_next_pc (&th->context);
999 th->step_prev = 0;
1000 memory_insert_breakpoint (th->step_pc, (void *) &th->step_prev);
1001 return;
1002}
1003#elif defined (ARM)
1004#undef check_for_step
1005
1006static enum target_signal
1007check_for_step (DEBUG_EVENT *ev, enum target_signal x)
1008{
1009 thread_info *th = thread_rec (ev->dwThreadId, 1);
1010
1011 if (th->stepped &&
1012 th->step_pc == (CORE_ADDR) ev->u.Exception.ExceptionRecord.ExceptionAddress)
1013 return TARGET_SIGNAL_TRAP;
1014 else
1015 return x;
1016}
1017
1018/* Single step (in a painstaking fashion) by inspecting the current
1019 instruction and setting a breakpoint on the "next" instruction
1020 which would be executed. This code hails from sh-stub.c.
1021 */
1022static void
1023undoSStep (thread_info * th)
1024{
1025 if (th->stepped)
1026 {
1027 memory_remove_breakpoint (th->step_pc, (void *) &th->step_prev);
1028 th->stepped = 0;
1029 }
1030}
1031
1032void
379d08a1
AC
1033wince_software_single_step (enum target_signal ignore,
1034 int insert_breakpoints_p)
61c37cee
CF
1035{
1036 unsigned long pc;
ca0b4d12
MS
1037 /* Info on currently selected thread. */
1038 thread_info *th = current_thread;
61c37cee
CF
1039 CORE_ADDR mips_next_pc (CORE_ADDR pc);
1040
1041 if (!insert_breakpoints_p)
1042 {
1043 undoSStep (th);
1044 return;
1045 }
1046
1047 th->stepped = 1;
1048 pc = read_register (PC_REGNUM);
1049 th->step_pc = arm_get_next_pc (pc);
1050 th->step_prev = 0;
1051 memory_insert_breakpoint (th->step_pc, (void *) &th->step_prev);
1052 return;
1053}
1054#endif
1055
0f07afe1 1056/* Find a thread record given a thread id.
ca0b4d12
MS
1057 If get_context then also retrieve the context for this thread. */
1058
0f07afe1
CF
1059static thread_info *
1060thread_rec (DWORD id, int get_context)
1061{
1062 thread_info *th;
1063
1064 for (th = &thread_head; (th = th->next) != NULL;)
1065 if (th->id == id)
1066 {
1067 if (!th->suspend_count && get_context)
1068 {
1069 if (get_context > 0 && th != this_thread)
1070 th->suspend_count = suspend_thread (th->h) + 1;
1071 else if (get_context < 0)
1072 th->suspend_count = -1;
1073
1074 th->context.ContextFlags = CONTEXT_DEBUGGER;
1075 get_thread_context (th->h, &th->context);
1076 }
1077 return th;
1078 }
0f07afe1
CF
1079 return NULL;
1080}
1081
ca0b4d12 1082/* Add a thread to the thread list. */
0f07afe1
CF
1083static thread_info *
1084child_add_thread (DWORD id, HANDLE h)
1085{
1086 thread_info *th;
1087
1088 if ((th = thread_rec (id, FALSE)))
1089 return th;
1090
1091 th = (thread_info *) xmalloc (sizeof (*th));
1092 memset (th, 0, sizeof (*th));
1093 th->id = id;
1094 th->h = h;
1095 th->next = thread_head.next;
1096 thread_head.next = th;
1097 add_thread (id);
1098 return th;
1099}
1100
1101/* Clear out any old thread list and reintialize it to a
ca0b4d12 1102 pristine state. */
0f07afe1 1103static void
fba45db2 1104child_init_thread_list (void)
0f07afe1
CF
1105{
1106 thread_info *th = &thread_head;
1107
1108 DEBUG_EVENTS (("gdb: child_init_thread_list\n"));
1109 init_thread_list ();
1110 while (th->next != NULL)
1111 {
1112 thread_info *here = th->next;
1113 th->next = here->next;
1114 (void) close_handle (here->h);
b8c9b27d 1115 xfree (here);
0f07afe1
CF
1116 }
1117}
1118
ca0b4d12 1119/* Delete a thread from the list of threads. */
0f07afe1
CF
1120static void
1121child_delete_thread (DWORD id)
1122{
1123 thread_info *th;
1124
1125 if (info_verbose)
1126 printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (id));
1127 delete_thread (id);
1128
1129 for (th = &thread_head;
1130 th->next != NULL && th->next->id != id;
1131 th = th->next)
1132 continue;
1133
1134 if (th->next != NULL)
1135 {
1136 thread_info *here = th->next;
1137 th->next = here->next;
1138 close_handle (here->h);
b8c9b27d 1139 xfree (here);
0f07afe1
CF
1140 }
1141}
1142
1143static void
1144check (BOOL ok, const char *file, int line)
1145{
1146 if (!ok)
ca0b4d12
MS
1147 printf_filtered ("error return %s:%d was %d\n",
1148 file, line, GetLastError ());
0f07afe1
CF
1149}
1150
0f07afe1
CF
1151static void
1152do_child_fetch_inferior_registers (int r)
1153{
1154 if (r >= 0)
1155 {
23a6d369
AC
1156 regcache_raw_supply (current_regcache, r,
1157 (char *) regptr (&current_thread->context, r));
0f07afe1
CF
1158 }
1159 else
1160 {
1161 for (r = 0; r < NUM_REGS; r++)
1162 do_child_fetch_inferior_registers (r);
1163 }
1164}
1165
1166static void
1167child_fetch_inferior_registers (int r)
1168{
39f77062 1169 current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
0f07afe1
CF
1170 do_child_fetch_inferior_registers (r);
1171}
1172
1173static void
1174do_child_store_inferior_registers (int r)
1175{
1176 if (r >= 0)
4caf0990 1177 deprecated_read_register_gen (r, ((char *) &current_thread->context) + mappings[r]);
0f07afe1
CF
1178 else
1179 {
1180 for (r = 0; r < NUM_REGS; r++)
1181 do_child_store_inferior_registers (r);
1182 }
1183}
1184
ca0b4d12 1185/* Store a new register value into the current thread context. */
0f07afe1
CF
1186static void
1187child_store_inferior_registers (int r)
1188{
39f77062 1189 current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
0f07afe1
CF
1190 do_child_store_inferior_registers (r);
1191}
1192
1193/* Wait for child to do something. Return pid of child, or -1 in case
1194 of error; store status through argument pointer OURSTATUS. */
1195
1196static int
9ff2efe5 1197handle_load_dll (void *dummy)
0f07afe1
CF
1198{
1199 LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
1200 char dll_buf[MAX_PATH + 1];
1201 char *p, *bufp, *imgp, *dll_name, *dll_basename;
1202 int len;
1203
1204 dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
1205 if (!event->lpImageName)
1206 return 1;
1207
1208 len = 0;
1209 for (bufp = dll_buf, imgp = event->lpImageName;
1210 bufp < dll_buf + sizeof (dll_buf);
1211 bufp += 16, imgp += 16)
1212 {
1213 gdb_wince_len nbytes = 0;
1214 (void) read_process_memory (current_process_handle,
1215 imgp, bufp, 16, &nbytes);
1216
1217 if (!nbytes && bufp == dll_buf)
1218 return 1; /* couldn't read it */
1219 for (p = bufp; p < bufp + nbytes; p++)
1220 {
1221 len++;
1222 if (*p == '\0')
1223 goto out;
1224 if (event->fUnicode)
1225 p++;
1226 }
1227 if (!nbytes)
1228 break;
1229 }
1230
1231out:
1232 if (!len)
1233 return 1;
61c37cee 1234#if 0
0f07afe1 1235 dll_buf[len] = '\0';
61c37cee 1236#endif
0f07afe1
CF
1237 dll_name = alloca (len);
1238
1239 if (!dll_name)
1240 return 1;
1241
1242 if (!event->fUnicode)
1243 memcpy (dll_name, dll_buf, len);
1244 else
ca0b4d12
MS
1245 WideCharToMultiByte (CP_ACP, 0, (LPCWSTR) dll_buf,
1246 len, dll_name, len, 0, 0);
0f07afe1
CF
1247
1248 while ((p = strchr (dll_name, '\\')))
1249 *p = '/';
1250
ca0b4d12
MS
1251 /* FIXME!! It would be nice to define one symbol which pointed to
1252 the front of the dll if we can't find any symbols. */
0f07afe1
CF
1253
1254 if (!(dll_basename = strrchr (dll_name, '/')))
1255 dll_basename = dll_name;
1256 else
1257 dll_basename++;
1258
1259 /* The symbols in a dll are offset by 0x1000, which is the
1260 the offset from 0 of the first byte in an image - because
1261 of the file header and the section alignment.
1262
1263 FIXME: Is this the real reason that we need the 0x1000 ? */
1264
1265 printf_unfiltered ("%x:%s", event->lpBaseOfDll, dll_name);
0f07afe1
CF
1266 printf_unfiltered ("\n");
1267
1268 return 1;
1269}
1270
ca0b4d12 1271/* Handle DEBUG_STRING output from child process. */
0f07afe1
CF
1272static void
1273handle_output_debug_string (struct target_waitstatus *ourstatus)
1274{
1275 char p[256];
1276 char s[255];
1277 char *q;
1278 gdb_wince_len nbytes_read;
1279 gdb_wince_len nbytes = current_event.u.DebugString.nDebugStringLength;
1280
1281 if (nbytes > 255)
1282 nbytes = 255;
1283
1284 memset (p, 0, sizeof (p));
1285 if (!read_process_memory (current_process_handle,
1286 current_event.u.DebugString.lpDebugStringData,
1287 &p, nbytes, &nbytes_read)
1288 || !*p)
1289 return;
1290
1291 memset (s, 0, sizeof (s));
ca0b4d12
MS
1292 WideCharToMultiByte (CP_ACP, 0, (LPCWSTR) p, (int) nbytes_read,
1293 s, sizeof (s) - 1, NULL, NULL);
0f07afe1
CF
1294 q = strchr (s, '\n');
1295 if (q != NULL)
1296 {
1297 *q = '\0';
1298 if (*--q = '\r')
1299 *q = '\0';
1300 }
1301
1302 warning (s);
61c37cee 1303
0f07afe1
CF
1304 return;
1305}
1306
ca0b4d12 1307/* Handle target exceptions. */
0f07afe1
CF
1308static int
1309handle_exception (struct target_waitstatus *ourstatus)
1310{
61c37cee 1311#if 0
0f07afe1
CF
1312 if (current_event.u.Exception.dwFirstChance)
1313 return 0;
61c37cee 1314#endif
0f07afe1
CF
1315
1316 ourstatus->kind = TARGET_WAITKIND_STOPPED;
1317
0f07afe1
CF
1318 switch (current_event.u.Exception.ExceptionRecord.ExceptionCode)
1319 {
1320 case EXCEPTION_ACCESS_VIOLATION:
1321 DEBUG_EXCEPT (("gdb: Target exception ACCESS_VIOLATION at 0x%08x\n",
1322 (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1323 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
1324 break;
1325 case STATUS_STACK_OVERFLOW:
1326 DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08x\n",
1327 (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1328 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
1329 break;
1330 case EXCEPTION_BREAKPOINT:
1331 DEBUG_EXCEPT (("gdb: Target exception BREAKPOINT at 0x%08x\n",
1332 (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1333 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
1334 break;
1335 case DBG_CONTROL_C:
1336 DEBUG_EXCEPT (("gdb: Target exception CONTROL_C at 0x%08x\n",
1337 (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1338 ourstatus->value.sig = TARGET_SIGNAL_INT;
ca0b4d12
MS
1339 /* User typed CTRL-C. Continue with this status. */
1340 last_sig = SIGINT; /* FIXME - should check pass state. */
0f07afe1
CF
1341 break;
1342 case EXCEPTION_SINGLE_STEP:
1343 DEBUG_EXCEPT (("gdb: Target exception SINGLE_STEP at 0x%08x\n",
1344 (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1345 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
1346 break;
61c37cee
CF
1347 case EXCEPTION_ILLEGAL_INSTRUCTION:
1348 DEBUG_EXCEPT (("gdb: Target exception SINGLE_ILL at 0x%08x\n",
ca0b4d12
MS
1349 /* (unsigned)? */ current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1350 ourstatus->value.sig = check_for_step (&current_event,
1351 TARGET_SIGNAL_ILL);
61c37cee 1352 break;
0f07afe1
CF
1353 default:
1354 /* This may be a structured exception handling exception. In
61c37cee
CF
1355 that case, we want to let the program try to handle it, and
1356 only break if we see the exception a second time. */
0f07afe1 1357
ca0b4d12
MS
1358 printf_unfiltered
1359 ("gdb: unknown target exception 0x%08x at 0x%08x\n",
1360 current_event.u.Exception.ExceptionRecord.ExceptionCode,
1361 current_event.u.Exception.ExceptionRecord.ExceptionAddress);
0f07afe1
CF
1362 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
1363 break;
1364 }
1365 exception_count++;
1366 return 1;
1367}
1368
1369/* Resume all artificially suspended threads if we are continuing
ca0b4d12 1370 execution. */
0f07afe1
CF
1371static BOOL
1372child_continue (DWORD continue_status, int id)
1373{
1374 int i;
1375 thread_info *th;
1376 BOOL res;
1377
1378 DEBUG_EVENTS (("ContinueDebugEvent (cpid=%d, ctid=%d, DBG_CONTINUE);\n",
ca0b4d12
MS
1379 (unsigned) current_event.dwProcessId,
1380 (unsigned) current_event.dwThreadId));
0f07afe1
CF
1381 res = continue_debug_event (current_event.dwProcessId,
1382 current_event.dwThreadId,
1383 continue_status);
1384 if (res)
1385 for (th = &thread_head; (th = th->next) != NULL;)
1386 if (((id == -1) || (id == th->id)) && th->suspend_count)
1387 {
1388 for (i = 0; i < th->suspend_count; i++)
1389 (void) resume_thread (th->h);
1390 th->suspend_count = 0;
1391 }
1392
1393 return res;
1394}
1395
1396/* Get the next event from the child. Return 1 if the event requires
1397 handling by WFI (or whatever).
1398 */
1399static int
61c37cee
CF
1400get_child_debug_event (int pid, struct target_waitstatus *ourstatus,
1401 DWORD target_event_code, int *retval)
0f07afe1 1402{
61c37cee 1403 int breakout = 0;
0f07afe1 1404 BOOL debug_event;
61c37cee
CF
1405 DWORD continue_status, event_code;
1406 thread_info *th = NULL;
1407 static thread_info dummy_thread_info;
0f07afe1
CF
1408
1409 if (!(debug_event = wait_for_debug_event (&current_event, 1000)))
1410 {
61c37cee 1411 *retval = 0;
0f07afe1
CF
1412 goto out;
1413 }
1414
0f07afe1
CF
1415 event_count++;
1416 continue_status = DBG_CONTINUE;
1417 *retval = 0;
61c37cee
CF
1418
1419 event_code = current_event.dwDebugEventCode;
1420 breakout = event_code == target_event_code;
1421
1422 switch (event_code)
0f07afe1
CF
1423 {
1424 case CREATE_THREAD_DEBUG_EVENT:
1425 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
1426 (unsigned) current_event.dwProcessId,
1427 (unsigned) current_event.dwThreadId,
1428 "CREATE_THREAD_DEBUG_EVENT"));
1429 /* Record the existence of this thread */
61c37cee
CF
1430 th = child_add_thread (current_event.dwThreadId,
1431 current_event.u.CreateThread.hThread);
0f07afe1
CF
1432 if (info_verbose)
1433 printf_unfiltered ("[New %s]\n",
1434 target_pid_to_str (current_event.dwThreadId));
1435 break;
1436
1437 case EXIT_THREAD_DEBUG_EVENT:
1438 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1439 (unsigned) current_event.dwProcessId,
1440 (unsigned) current_event.dwThreadId,
1441 "EXIT_THREAD_DEBUG_EVENT"));
1442 child_delete_thread (current_event.dwThreadId);
61c37cee 1443 th = &dummy_thread_info;
0f07afe1
CF
1444 break;
1445
1446 case CREATE_PROCESS_DEBUG_EVENT:
1447 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1448 (unsigned) current_event.dwProcessId,
1449 (unsigned) current_event.dwThreadId,
1450 "CREATE_PROCESS_DEBUG_EVENT"));
1451 current_process_handle = current_event.u.CreateProcessInfo.hProcess;
1452
39f77062
KB
1453 main_thread_id = current_event.dwThreadId;
1454 inferior_ptid = pid_to_ptid (main_thread_id);
0f07afe1 1455 /* Add the main thread */
39f77062 1456 th = child_add_thread (PIDGET (inferior_ptid),
61c37cee 1457 current_event.u.CreateProcessInfo.hThread);
0f07afe1
CF
1458 break;
1459
1460 case EXIT_PROCESS_DEBUG_EVENT:
1461 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1462 (unsigned) current_event.dwProcessId,
1463 (unsigned) current_event.dwThreadId,
1464 "EXIT_PROCESS_DEBUG_EVENT"));
1465 ourstatus->kind = TARGET_WAITKIND_EXITED;
1466 ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
1467 close_handle (current_process_handle);
1468 *retval = current_event.dwProcessId;
61c37cee
CF
1469 breakout = 1;
1470 break;
0f07afe1
CF
1471
1472 case LOAD_DLL_DEBUG_EVENT:
1473 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1474 (unsigned) current_event.dwProcessId,
1475 (unsigned) current_event.dwThreadId,
1476 "LOAD_DLL_DEBUG_EVENT"));
ca0b4d12
MS
1477 catch_errors (handle_load_dll, NULL,
1478 (char *) "", RETURN_MASK_ALL);
0f07afe1
CF
1479 registers_changed (); /* mark all regs invalid */
1480 break;
1481
1482 case UNLOAD_DLL_DEBUG_EVENT:
1483 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1484 (unsigned) current_event.dwProcessId,
1485 (unsigned) current_event.dwThreadId,
1486 "UNLOAD_DLL_DEBUG_EVENT"));
1487 break; /* FIXME: don't know what to do here */
1488
1489 case EXCEPTION_DEBUG_EVENT:
1490 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1491 (unsigned) current_event.dwProcessId,
1492 (unsigned) current_event.dwThreadId,
1493 "EXCEPTION_DEBUG_EVENT"));
1494 if (handle_exception (ourstatus))
61c37cee
CF
1495 *retval = current_event.dwThreadId;
1496 else
0f07afe1 1497 {
61c37cee
CF
1498 continue_status = DBG_EXCEPTION_NOT_HANDLED;
1499 breakout = 0;
0f07afe1 1500 }
0f07afe1
CF
1501 break;
1502
1503 case OUTPUT_DEBUG_STRING_EVENT: /* message from the kernel */
1504 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1505 (unsigned) current_event.dwProcessId,
1506 (unsigned) current_event.dwThreadId,
1507 "OUTPUT_DEBUG_STRING_EVENT"));
61c37cee 1508 handle_output_debug_string ( ourstatus);
0f07afe1
CF
1509 break;
1510 default:
1511 printf_unfiltered ("gdb: kernel event for pid=%d tid=%d\n",
1512 current_event.dwProcessId,
1513 current_event.dwThreadId);
1514 printf_unfiltered (" unknown event code %d\n",
1515 current_event.dwDebugEventCode);
1516 break;
1517 }
1518
61c37cee 1519 if (breakout)
ca0b4d12
MS
1520 this_thread = current_thread = th ?: thread_rec (current_event.dwThreadId,
1521 TRUE);
61c37cee
CF
1522 else
1523 CHECK (child_continue (continue_status, -1));
0f07afe1
CF
1524
1525out:
1526 return breakout;
1527}
1528
ca0b4d12 1529/* Wait for interesting events to occur in the target process. */
39f77062
KB
1530static ptid_t
1531child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
0f07afe1
CF
1532{
1533 DWORD event_code;
1534 int retval;
39f77062 1535 int pid = PIDGET (ptid);
0f07afe1
CF
1536
1537 /* We loop when we get a non-standard exception rather than return
1538 with a SPURIOUS because resume can try and step or modify things,
1539 which needs a current_thread->h. But some of these exceptions mark
1540 the birth or death of threads, which mean that the current thread
ca0b4d12 1541 isn't necessarily what you think it is. */
0f07afe1
CF
1542
1543 while (1)
ca0b4d12
MS
1544 if (get_child_debug_event (pid, ourstatus,
1545 EXCEPTION_DEBUG_EVENT, &retval))
39f77062 1546 return pid_to_ptid (retval);
0f07afe1
CF
1547 else
1548 {
1549 int detach = 0;
1550
98bbd631
AC
1551 if (deprecated_ui_loop_hook != NULL)
1552 detach = deprecated_ui_loop_hook (0);
0f07afe1
CF
1553
1554 if (detach)
1555 child_kill_inferior ();
1556 }
1557}
1558
1559/* Print status information about what we're accessing. */
1560
1561static void
fba45db2 1562child_files_info (struct target_ops *ignore)
0f07afe1
CF
1563{
1564 printf_unfiltered ("\tUsing the running image of child %s.\n",
39f77062 1565 target_pid_to_str (inferior_ptid));
0f07afe1
CF
1566}
1567
0f07afe1 1568static void
fba45db2 1569child_open (char *arg, int from_tty)
0f07afe1 1570{
8a3fe4f8 1571 error (_("Use the \"run\" command to start a child process."));
0f07afe1
CF
1572}
1573
1574#define FACTOR (0x19db1ded53ea710LL)
1575#define NSPERSEC 10000000
1576
ca0b4d12 1577/* Convert a Win32 time to "UNIX" format. */
0f07afe1
CF
1578long
1579to_time_t (FILETIME * ptr)
1580{
1581 /* A file time is the number of 100ns since jan 1 1601
1582 stuffed into two long words.
1583 A time_t is the number of seconds since jan 1 1970. */
1584
1585 long rem;
1586 long long x = ((long long) ptr->dwHighDateTime << 32) + ((unsigned) ptr->dwLowDateTime);
ca0b4d12 1587 x -= FACTOR; /* Number of 100ns between 1601 and 1970. */
0f07afe1
CF
1588 rem = x % ((long long) NSPERSEC);
1589 rem += (NSPERSEC / 2);
ca0b4d12 1590 x /= (long long) NSPERSEC; /* Number of 100ns in a second. */
0f07afe1
CF
1591 x += (long long) (rem / NSPERSEC);
1592 return x;
1593}
1594
1595/* Upload a file to the remote device depending on the user's
ca0b4d12 1596 'set remoteupload' specification. */
0f07afe1
CF
1597char *
1598upload_to_device (const char *to, const char *from)
1599{
1600 HANDLE h;
61c37cee 1601 const char *dir = remote_directory ?: "\\gdb";
0f07afe1
CF
1602 int len;
1603 static char *remotefile = NULL;
1604 LPWSTR wstr;
1605 char *p;
1606 DWORD err;
1607 const char *in_to = to;
61c37cee
CF
1608 FILETIME crtime, actime, wrtime;
1609 time_t utime;
0f07afe1
CF
1610 struct stat st;
1611 int fd;
1612
ca0b4d12 1613 /* Look for a path separator and only use trailing part. */
0f07afe1
CF
1614 while ((p = strpbrk (to, "/\\")) != NULL)
1615 to = p + 1;
1616
1617 if (!*to)
8a3fe4f8 1618 error (_("no filename found to upload - %s."), in_to);
0f07afe1
CF
1619
1620 len = strlen (dir) + strlen (to) + 2;
9ff2efe5 1621 remotefile = (char *) xrealloc (remotefile, len);
0f07afe1
CF
1622 strcpy (remotefile, dir);
1623 strcat (remotefile, "\\");
1624 strcat (remotefile, to);
1625
1626 if (upload_when == UPLOAD_NEVER)
ca0b4d12 1627 return remotefile; /* Don't bother uploading. */
0f07afe1 1628
ca0b4d12
MS
1629 /* Open the source. */
1630 if ((fd = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, (char *) from,
1631 O_RDONLY, 0, NULL)) < 0)
8a3fe4f8 1632 error (_("couldn't open %s"), from);
0f07afe1 1633
ca0b4d12 1634 /* Get the time for later comparison. */
0f07afe1
CF
1635 if (fstat (fd, &st))
1636 st.st_mtime = (time_t) - 1;
1637
ca0b4d12 1638 /* Always attempt to create the directory on the remote system. */
0f07afe1
CF
1639 wstr = towide (dir, NULL);
1640 (void) CeCreateDirectory (wstr, NULL);
1641
ca0b4d12 1642 /* Attempt to open the remote file, creating it if it doesn't exist. */
0f07afe1
CF
1643 wstr = towide (remotefile, NULL);
1644 h = CeCreateFile (wstr, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1645 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1646
ca0b4d12 1647 /* Some kind of problem? */
0f07afe1 1648 err = CeGetLastError ();
61c37cee 1649 if (h == NULL || h == INVALID_HANDLE_VALUE)
8a3fe4f8 1650 error (_("error opening file \"%s\". Windows error %d."),
0f07afe1
CF
1651 remotefile, err);
1652
61c37cee
CF
1653 CeGetFileTime (h, &crtime, &actime, &wrtime);
1654 utime = to_time_t (&wrtime);
1655#if 0
1656 if (utime < st.st_mtime)
1657 {
1658 char buf[80];
1659 strcpy (buf, ctime(&utime));
1660 printf ("%s < %s\n", buf, ctime(&st.st_mtime));
1661 }
1662#endif
ca0b4d12 1663 /* See if we need to upload the file. */
0f07afe1
CF
1664 if (upload_when == UPLOAD_ALWAYS ||
1665 err != ERROR_ALREADY_EXISTS ||
61c37cee
CF
1666 !CeGetFileTime (h, &crtime, &actime, &wrtime) ||
1667 to_time_t (&wrtime) < st.st_mtime)
0f07afe1
CF
1668 {
1669 DWORD nbytes;
1670 char buf[4096];
1671 int n;
1672
ca0b4d12 1673 /* Upload the file. */
0f07afe1
CF
1674 while ((n = read (fd, buf, sizeof (buf))) > 0)
1675 if (!CeWriteFile (h, buf, (DWORD) n, &nbytes, NULL))
8a3fe4f8 1676 error (_("error writing to remote device - %d."),
0f07afe1
CF
1677 CeGetLastError ());
1678 }
1679
1680 close (fd);
61c37cee 1681 if (!CeCloseHandle (h))
8a3fe4f8 1682 error (_("error closing remote file - %d."), CeGetLastError ());
0f07afe1
CF
1683
1684 return remotefile;
1685}
1686
ca0b4d12 1687/* Initialize the connection to the remote device. */
0f07afe1 1688static void
fba45db2 1689wince_initialize (void)
0f07afe1
CF
1690{
1691 int tmp;
1692 char args[256];
1693 char *hostname;
1694 struct sockaddr_in sin;
1695 char *stub_file_name;
1696 int s0;
1697 PROCESS_INFORMATION pi;
1698
1699 if (!connection_initialized)
1700 switch (CeRapiInit ())
1701 {
1702 case 0:
1703 connection_initialized = 1;
1704 break;
1705 default:
1706 CeRapiUninit ();
8a3fe4f8 1707 error (_("Can't initialize connection to remote device."));
0f07afe1
CF
1708 }
1709
ca0b4d12 1710 /* Upload the stub to the handheld device. */
0f07afe1
CF
1711 stub_file_name = upload_to_device ("wince-stub.exe", WINCE_STUB);
1712 strcpy (args, stub_file_name);
1713
1714 if (remote_add_host)
1715 {
1716 strcat (args, " ");
1717 hostname = strchr (args, '\0');
1718 if (gethostname (hostname, sizeof (args) - strlen (args)))
8a3fe4f8 1719 error (_("couldn't get hostname of this system."));
0f07afe1
CF
1720 }
1721
ca0b4d12 1722 /* Get a socket. */
0f07afe1
CF
1723 if ((s0 = socket (AF_INET, SOCK_STREAM, 0)) < 0)
1724 stub_error ("Couldn't connect to host system.");
1725
ca0b4d12 1726 /* Allow rapid reuse of the port. */
0f07afe1 1727 tmp = 1;
ca0b4d12
MS
1728 (void) setsockopt (s0, SOL_SOCKET, SO_REUSEADDR,
1729 (char *) &tmp, sizeof (tmp));
0f07afe1
CF
1730
1731
ca0b4d12 1732 /* Set up the information for connecting to the host gdb process. */
0f07afe1
CF
1733 memset (&sin, 0, sizeof (sin));
1734 sin.sin_family = AF_INET;
ca0b4d12 1735 sin.sin_port = htons (7000); /* FIXME: This should be configurable. */
0f07afe1
CF
1736
1737 if (bind (s0, (struct sockaddr *) &sin, sizeof (sin)))
8a3fe4f8 1738 error (_("couldn't bind socket"));
0f07afe1
CF
1739
1740 if (listen (s0, 1))
8a3fe4f8 1741 error (_("Couldn't open socket for listening."));
0f07afe1 1742
ca0b4d12
MS
1743 /* Start up the stub on the remote device. */
1744 if (!CeCreateProcess (towide (stub_file_name, NULL),
1745 towide (args, NULL),
1746 NULL, NULL, 0, 0,
1747 NULL, NULL, NULL, &pi))
8a3fe4f8 1748 error (_("Unable to start remote stub '%s'. Windows CE error %d."),
0f07afe1
CF
1749 stub_file_name, CeGetLastError ());
1750
1751 /* Wait for a connection */
1752
1753 if ((s = accept (s0, NULL, NULL)) < 0)
8a3fe4f8 1754 error (_("couldn't set up server for connection."));
0f07afe1
CF
1755
1756 close (s0);
1757}
1758
39f77062 1759/* Start an inferior win32 child process and sets inferior_ptid to its pid.
0f07afe1
CF
1760 EXEC_FILE is the file to run.
1761 ALLARGS is a string containing the arguments to the program.
ca0b4d12
MS
1762 ENV is the environment vector to pass.
1763 Errors reported with error(). */
0f07afe1 1764static void
c27cda74
AC
1765child_create_inferior (char *exec_file, char *args, char **env,
1766 int from_tty)
0f07afe1
CF
1767{
1768 PROCESS_INFORMATION pi;
1769 struct target_waitstatus dummy;
1770 int ret;
1771 DWORD flags, event_code;
1772 char *exec_and_args;
1773
1774 if (!exec_file)
8a3fe4f8 1775 error (_("No executable specified, use `target exec'."));
0f07afe1
CF
1776
1777 flags = DEBUG_PROCESS;
1778
ca0b4d12 1779 wince_initialize (); /* Make sure we've got a connection. */
0f07afe1
CF
1780
1781 exec_file = upload_to_device (exec_file, exec_file);
1782
1783 while (*args == ' ')
1784 args++;
1785
1786 /* Allocate space for "command<sp>args" */
1787 if (*args == '\0')
1788 {
1789 exec_and_args = alloca (strlen (exec_file) + 1);
1790 strcpy (exec_and_args, exec_file);
1791 }
1792 else
1793 {
1794 exec_and_args = alloca (strlen (exec_file + strlen (args) + 2));
1795 sprintf (exec_and_args, "%s %s", exec_file, args);
1796 }
1797
1798 memset (&pi, 0, sizeof (pi));
ca0b4d12 1799 /* Execute the process. */
0f07afe1 1800 if (!create_process (exec_file, exec_and_args, flags, &pi))
8a3fe4f8 1801 error (_("Error creating process %s, (error %d)."),
ca0b4d12 1802 exec_file, GetLastError ());
0f07afe1
CF
1803
1804 exception_count = 0;
1805 event_count = 0;
1806
1807 current_process_handle = pi.hProcess;
1808 current_event.dwProcessId = pi.dwProcessId;
1809 memset (&current_event, 0, sizeof (current_event));
39f77062
KB
1810 current_event.dwThreadId = pi.dwThreadId;
1811 inferior_ptid = pid_to_ptid (current_event.dwThreadId);
1df84f13 1812 push_target (&deprecated_child_ops);
0f07afe1
CF
1813 child_init_thread_list ();
1814 child_add_thread (pi.dwThreadId, pi.hThread);
1815 init_wait_for_inferior ();
1816 clear_proceed_status ();
1817 target_terminal_init ();
1818 target_terminal_inferior ();
1819
0f07afe1 1820 /* Run until process and threads are loaded */
39f77062 1821 while (!get_child_debug_event (PIDGET (inferior_ptid), &dummy,
61c37cee
CF
1822 CREATE_PROCESS_DEBUG_EVENT, &ret))
1823 continue;
0f07afe1
CF
1824
1825 proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
1826}
1827
ca0b4d12 1828/* Chile has gone bye-bye. */
0f07afe1 1829static void
fba45db2 1830child_mourn_inferior (void)
0f07afe1
CF
1831{
1832 (void) child_continue (DBG_CONTINUE, -1);
1df84f13 1833 unpush_target (&deprecated_child_ops);
0f07afe1
CF
1834 stop_stub ();
1835 CeRapiUninit ();
1836 connection_initialized = 0;
1837 generic_mourn_inferior ();
1838}
1839
ca0b4d12 1840/* Move memory from child to/from gdb. */
0f07afe1 1841int
ca0b4d12
MS
1842child_xfer_memory (CORE_ADDR memaddr, char *our,
1843 int len, int write,
043780a1
AC
1844 struct mem_attrib *attrib,
1845 struct target_ops *target)
0f07afe1
CF
1846{
1847 if (len <= 0)
1848 return 0;
4930751a
C
1849
1850 if (write)
1851 res = remote_write_bytes (memaddr, our, len);
1852 else
1853 res = remote_read_bytes (memaddr, our, len);
1854
1855 return res;
0f07afe1
CF
1856}
1857
ca0b4d12
MS
1858/* Terminate the process and wait for child to tell us it has
1859 completed. */
0f07afe1
CF
1860void
1861child_kill_inferior (void)
1862{
1863 CHECK (terminate_process (current_process_handle));
1864
1865 for (;;)
1866 {
1867 if (!child_continue (DBG_CONTINUE, -1))
1868 break;
1869 if (!wait_for_debug_event (&current_event, INFINITE))
1870 break;
1871 if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
1872 break;
1873 }
1874
1875 CHECK (close_handle (current_process_handle));
1876 close_handle (current_thread->h);
ca0b4d12 1877 target_mourn_inferior (); /* or just child_mourn_inferior? */
0f07afe1
CF
1878}
1879
ca0b4d12 1880/* Resume the child after an exception. */
0f07afe1 1881void
39f77062 1882child_resume (ptid_t ptid, int step, enum target_signal sig)
0f07afe1
CF
1883{
1884 thread_info *th;
1885 DWORD continue_status = last_sig > 0 && last_sig < NSIG ?
ca0b4d12 1886 DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE;
39f77062 1887 int pid = PIDGET (ptid);
0f07afe1
CF
1888
1889 DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, sig=%d);\n",
1890 pid, step, sig));
1891
1892 /* Get context for currently selected thread */
1893 th = thread_rec (current_event.dwThreadId, FALSE);
1894
1895 if (th->context.ContextFlags)
1896 {
1897 CHECK (set_thread_context (th->h, &th->context));
1898 th->context.ContextFlags = 0;
1899 }
1900
0f07afe1 1901 /* Allow continuing with the same signal that interrupted us.
ca0b4d12 1902 Otherwise complain. */
0f07afe1 1903 if (sig && sig != last_sig)
ca0b4d12
MS
1904 fprintf_unfiltered (gdb_stderr,
1905 "Can't send signals to the child. signal %d\n",
1906 sig);
0f07afe1
CF
1907
1908 last_sig = 0;
1909 child_continue (continue_status, pid);
1910}
1911
1912static void
fba45db2 1913child_prepare_to_store (void)
0f07afe1
CF
1914{
1915 /* Do nothing, since we can store individual regs */
1916}
1917
1918static int
fba45db2 1919child_can_run (void)
0f07afe1
CF
1920{
1921 return 1;
1922}
1923
1924static void
fba45db2 1925child_close (void)
0f07afe1 1926{
39f77062 1927 DEBUG_EVENTS (("gdb: child_close, inferior_ptid=%d\n",
ca0b4d12 1928 PIDGET (inferior_ptid)));
0f07afe1
CF
1929}
1930
1931/* Explicitly upload file to remotedir */
1932
1933static void
1934child_load (char *file, int from_tty)
1935{
1936 upload_to_device (file, file);
1937}
1938
0f07afe1
CF
1939static void
1940init_child_ops (void)
1941{
1df84f13
AC
1942 memset (&deprecated_child_ops, 0, sizeof (deprecated_child_ops));
1943 deprecated_child_ops.to_shortname = (char *) "child";
1944 deprecated_child_ops.to_longname = (char *) "Windows CE process";
1945 deprecated_child_ops.to_doc = (char *) "Windows CE process (started by the \"run\" command).";
1946 deprecated_child_ops.to_open = child_open;
1947 deprecated_child_ops.to_close = child_close;
1948 deprecated_child_ops.to_resume = child_resume;
1949 deprecated_child_ops.to_wait = child_wait;
1950 deprecated_child_ops.to_fetch_registers = child_fetch_inferior_registers;
1951 deprecated_child_ops.to_store_registers = child_store_inferior_registers;
1952 deprecated_child_ops.to_prepare_to_store = child_prepare_to_store;
c8e73a31 1953 deprecated_child_ops.deprecated_xfer_memory = child_xfer_memory;
1df84f13
AC
1954 deprecated_child_ops.to_files_info = child_files_info;
1955 deprecated_child_ops.to_insert_breakpoint = memory_insert_breakpoint;
1956 deprecated_child_ops.to_remove_breakpoint = memory_remove_breakpoint;
1957 deprecated_child_ops.to_terminal_init = terminal_init_inferior;
1958 deprecated_child_ops.to_terminal_inferior = terminal_inferior;
1959 deprecated_child_ops.to_terminal_ours_for_output = terminal_ours_for_output;
1960 deprecated_child_ops.to_terminal_ours = terminal_ours;
1961 deprecated_child_ops.to_terminal_save_ours = terminal_save_ours;
1962 deprecated_child_ops.to_terminal_info = child_terminal_info;
1963 deprecated_child_ops.to_kill = child_kill_inferior;
1964 deprecated_child_ops.to_load = child_load;
1965 deprecated_child_ops.to_create_inferior = child_create_inferior;
1966 deprecated_child_ops.to_mourn_inferior = child_mourn_inferior;
1967 deprecated_child_ops.to_can_run = child_can_run;
1968 deprecated_child_ops.to_thread_alive = win32_child_thread_alive;
1969 deprecated_child_ops.to_stratum = process_stratum;
1970 deprecated_child_ops.to_has_all_memory = 1;
1971 deprecated_child_ops.to_has_memory = 1;
1972 deprecated_child_ops.to_has_stack = 1;
1973 deprecated_child_ops.to_has_registers = 1;
1974 deprecated_child_ops.to_has_execution = 1;
1975 deprecated_child_ops.to_magic = OPS_MAGIC;
0f07afe1
CF
1976}
1977
1978
ca0b4d12 1979/* Handle 'set remoteupload' parameter. */
0f07afe1
CF
1980
1981#define replace_upload(what) \
ca0b4d12
MS
1982 upload_when = what; \
1983 remote_upload = xrealloc (remote_upload, \
1984 strlen (upload_options[upload_when].name) + 1); \
1985 strcpy (remote_upload, upload_options[upload_when].name);
0f07afe1
CF
1986
1987static void
1988set_upload_type (char *ignore, int from_tty)
1989{
1990 int i, len;
1991 char *bad_option;
1992
1993 if (!remote_upload || !remote_upload[0])
1994 {
1995 replace_upload (UPLOAD_NEWER);
1996 if (from_tty)
1997 printf_unfiltered ("Upload upload_options are: always, newer, never.\n");
1998 return;
1999 }
2000
2001 len = strlen (remote_upload);
ca0b4d12
MS
2002 for (i = 0;
2003 i < (sizeof (upload_options) / sizeof (upload_options[0]));
2004 i++)
0f07afe1
CF
2005 if (len >= upload_options[i].abbrev &&
2006 strncasecmp (remote_upload, upload_options[i].name, len) == 0)
2007 {
61c37cee 2008 replace_upload (i);
0f07afe1
CF
2009 return;
2010 }
2011
2012 bad_option = remote_upload;
2013 replace_upload (UPLOAD_NEWER);
8a3fe4f8 2014 error (_("Unknown upload type: %s."), bad_option);
0f07afe1
CF
2015}
2016
2017void
a6b6b089 2018_initialize_wince (void)
0f07afe1
CF
2019{
2020 struct cmd_list_element *set;
2021 init_child_ops ();
2022
26c41df3
AC
2023 add_setshow_string_noescape_cmd ("remotedirectory", no_class,
2024 &remote_directory, _("\
2025Set directory for remote upload."), _("\
2026Show directory for remote upload."), NULL,
2027 NULL, /* FIXME: i18n: */
2028 NULL, NULL,
2029 &setlist, &showlist);
0f07afe1
CF
2030 remote_directory = xstrdup (remote_directory);
2031
26c41df3
AC
2032 add_setshow_string_noescape_cmd ("remoteupload", no_class,
2033 &remote_upload, _("\
2034Set how to upload executables to remote device."), _("\
2035Show how to upload executables to remote device."), NULL,
2036 NULL, /* FIXME: i18n: */
2037 set_upload_type, NULL,
2038 &setlist, &showlist);
0f07afe1 2039 set_upload_type (NULL, 0);
0f07afe1 2040
5bf193a2
AC
2041 add_setshow_boolean_cmd ("debugexec", class_support, &debug_exec, _("\
2042Set whether to display execution in child process."), _("\
2043Show whether to display execution in child process."), NULL,
2044 NULL,
2045 NULL, /* FIXME: i18n: */
2046 &setlist, &showlist);
2047
2048 add_setshow_boolean_cmd ("remoteaddhost", class_support,
2049 &remote_add_host, _("\
7be0c536 2050Set whether to add this host to remote stub arguments for\n\
5bf193a2
AC
2051debugging over a network."), _("\
2052Show whether to add this host to remote stub arguments for\n\
2053debugging over a network."), NULL,
2054 NULL,
2055 NULL, /* FIXME: i18n: */
2056 &setlist, &showlist);
2057
2058 add_setshow_boolean_cmd ("debugevents", class_support, &debug_events, _("\
2059Set whether to display kernel events in child process."), _("\
2060Show whether to display kernel events in child process."), NULL,
2061 NULL,
2062 NULL, /* FIXME: i18n: */
2063 &setlist, &showlist);
2064
2065 add_setshow_boolean_cmd ("debugmemory", class_support, &debug_memory, _("\
2066Set whether to display memory accesses in child process."), _("\
2067Show whether to display memory accesses in child process."), NULL,
2068 NULL,
2069 NULL, /* FIXME: i18n: */
2070 &setlist, &showlist);
2071
2072 add_setshow_boolean_cmd ("debugexceptions", class_support,
2073 &debug_exceptions, _("\
2074Set whether to display kernel exceptions in child process."), _("\
2075Show whether to display kernel exceptions in child process."), NULL,
2076 NULL,
2077 NULL, /* FIXME: i18n: */
2078 &setlist, &showlist);
0f07afe1 2079
1df84f13 2080 add_target (&deprecated_child_ops);
0f07afe1
CF
2081}
2082
ca0b4d12
MS
2083/* Determine if the thread referenced by "pid" is alive by "polling"
2084 it. If WaitForSingleObject returns WAIT_OBJECT_0 it means that the
2085 pid has died. Otherwise it is assumed to be alive. */
0f07afe1 2086static int
39f77062 2087win32_child_thread_alive (ptid_t ptid)
0f07afe1 2088{
39f77062 2089 int pid = PIDGET (ptid);
0f07afe1
CF
2090 return thread_alive (thread_rec (pid, FALSE)->h);
2091}
2092
ca0b4d12 2093/* Convert pid to printable format. */
0f07afe1
CF
2094char *
2095cygwin_pid_to_str (int pid)
2096{
2097 static char buf[80];
2098 if (pid == current_event.dwProcessId)
2099 sprintf (buf, "process %d", pid);
2100 else
ca0b4d12
MS
2101 sprintf (buf, "thread %d.0x%x",
2102 (unsigned) current_event.dwProcessId, pid);
0f07afe1
CF
2103 return buf;
2104}
This page took 0.641839 seconds and 4 git commands to generate.