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